DrGraph图形博士

导航

风火轮 –动画效果:擦除、形状、轮子、随机线条、翻转远近、缩放、旋转、弹跳效果

今天再花了一个白天时间,把PPT动画的进入效果全部实现。

  1. 浮入效果

头文件

 

 

class TCbwAnimationEffect_Erase : public TCbwAnimationEffect { // 擦除

    virtual void __fastcall BuildMaskMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

public:

    __fastcall TCbwAnimationEffect_Erase();

    static TCbwAnimationEffect * Build();

};

 

class TCbwAnimationEffect_Shape : public TCbwAnimationEffect { // 形状

    virtual void __fastcall BuildMaskMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

public:

    __fastcall TCbwAnimationEffect_Shape();

    static TCbwAnimationEffect * Build();

};

 

class TCbwAnimationEffect_Wheel : public TCbwAnimationEffect { // 轮子

    virtual void __fastcall BuildMaskMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

public:

    __fastcall TCbwAnimationEffect_Wheel();

    static TCbwAnimationEffect * Build();

};

 

class TCbwAnimationEffect_RandomLine : public TCbwAnimationEffect { // 随机线

    virtual void __fastcall BuildMaskMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

    BYTE * FOccurredLines;

 

public:

    __fastcall TCbwAnimationEffect_RandomLine();

    static TCbwAnimationEffect * Build();

};

 

 

class TCbwAnimationEffect_RotateToNear : public TCbwAnimationEffect_SameMask

{ // 翻转式由远及近

    virtual void __fastcall BuildDisplayMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

public:

    __fastcall TCbwAnimationEffect_RotateToNear();

    static TCbwAnimationEffect * Build();

};

 

class TCbwAnimationEffect_Zoom : public TCbwAnimationEffect_SameMask { // 缩放

    virtual void __fastcall BuildDisplayMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

public:

    __fastcall TCbwAnimationEffect_Zoom();

    static TCbwAnimationEffect * Build();

};

 

class TCbwAnimationEffect_Rotate : public TCbwAnimationEffect_SameMask { // 旋转

    virtual void __fastcall BuildDisplayMat(cv::Mat& destMat, cv::Mat& srcMat,

        TRect displayRect);

 

public:

    __fastcall TCbwAnimationEffect_Rotate();

    static TCbwAnimationEffect * Build();

};

 

class TCbwAnimationEffect_Bounce : public TCbwAnimationEffect { // 随机线

    virtual TRect __fastcall BuildDisplayRect(OBJECTMAT * m);

public:

    __fastcall TCbwAnimationEffect_Bounce();

    static TCbwAnimationEffect * Build();

};

 

实现:

 

// ***************************** 擦除效果 **************************************

__fastcall TCbwAnimationEffect_Erase::TCbwAnimationEffect_Erase()

    : TCbwAnimationEffect() {

    EffectType = cetErase;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_Erase::Build() {

    return new TCbwAnimationEffect_Erase;

}

 

void __fastcall TCbwAnimationEffect_Erase::BuildMaskMat(cv::Mat& destMat,

    cv::Mat& srcMat, TRect displayRect) {

    int effectOptionType = MyOptionType.Items[1].CurrentValue * 2;

    // 为了共用CbwEffectDirection类型

    TRect wholeRect(0, 0, displayRect.right - displayRect.left,

        displayRect.bottom - displayRect.top);

    TRect partRect = wholeRect;

    bool vertFlag =

        (cedFromBottom == effectOptionType || cedFromTop == effectOptionType);

    double delta = double(FCurrentIndex + 1) / FPeriodLength * (vertFlag ?

        partRect.bottom : partRect.right);

    if (cedFromBottom == effectOptionType) // 自底部

            partRect.top = partRect.bottom - delta;

    if (cedFromLeft == effectOptionType) // 自左侧

            partRect.right = partRect.left + delta;

    if (cedFromTop == effectOptionType) // 自顶部

            partRect.bottom = partRect.top + delta;

    if (cedFromRight == effectOptionType) // 自右侧

            partRect.left = partRect.right - delta;

    BYTE * pSrc = srcMat.data;

    BYTE * pDst = destMat.data;

    for (int row = 0; row < destMat.rows; ++row)

        for (int col = 0; col < destMat.cols; ++col) {

            bool hasValueFlag = (*pSrc++ != 0);

            if (!hasValueFlag)

                * pDst = 0;

            int y = (row - partRect.top) * (partRect.bottom - row);

            int x = (col - partRect.left) * (partRect.right - col);

            bool inFlag = (y >= 0 && x >= 0);

            *pDst++ = (inFlag ? 255 : 0);

        }

}

// ***************************** 擦除效果 **************************************

 

// ***************************** 形状效果 **************************************

__fastcall TCbwAnimationEffect_Shape::TCbwAnimationEffect_Shape()

    : TCbwAnimationEffect() {

    EffectType = cetShape;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_Shape::Build() {

    return new TCbwAnimationEffect_Shape;

}

 

void __fastcall TCbwAnimationEffect_Shape::BuildMaskMat(cv::Mat& destMat,

    cv::Mat& srcMat, TRect displayRect) {

    int zoomType = MyOptionType.Items[1].CurrentValue; // 放大、缩小

    int shapeType = MyOptionType.Items[2].CurrentValue; // 类型

    TRect wholeRect(0, 0, displayRect.right - displayRect.left,

        displayRect.bottom - displayRect.top);

    double cx = wholeRect.right / 2.0, cy = wholeRect.bottom / 2.0;

    double deltaX = double(FCurrentIndex + 1) / FPeriodLength * cx;

    double deltaY = double(FCurrentIndex + 1) / FPeriodLength * cy;

    double startX = deltaX, startY = deltaY;

    double endX = wholeRect.right - deltaX, endY = wholeRect.bottom - deltaY;

 

    if (zoomType == csdZoomOut) {

        startX = cx - deltaX;

        startY = cy - deltaY;

        endX = cx + deltaX;

        endY = cy + deltaY;

    }

    BYTE * pSrc = srcMat.data;

    BYTE * pDst = destMat.data;

    for (int row = 0; row < destMat.rows; ++row)

        for (int col = 0; col < destMat.cols; ++col) {

            bool hasValueFlag = (*pSrc++ != 0);

            if (!hasValueFlag)

                * pDst = 0;

            bool inFlag = false;

            double a = (cx - startX) * 1.5, b = (cy - startY) * 1.5;

            if (shapeType == cstCircle) { // 圆

                if (a > 0 && b > 0) {

                    double v = (row - cy) * (row - cy) / (b * b) +

                        (col - cx) * (col - cx) / (a * a);

                    inFlag = (v <= 1);

                }

            }

            if (shapeType == cstRect) { // 方框

                inFlag =

                    (fabs(cx - startX) >= fabs(cx - col) && fabs(cy - startY) >=

                    fabs(cy - row));

            }

            if (shapeType == cstDiamond) { // 菱形

                if (a > 0 && b > 0) {

                    if (zoomType == csdZoomOut) {

                        a *= 2;

                        b *= 2;

                    }

                    bool lr1 = (col < (((-a) * (1 - (row - cy) / (b))) + cx));

                    bool lr2 = (col < (((-a) * (1 - (row - cy) / (-b))) + cx));

                    bool lr3 = (col < (((a) * (1 - (row - cy) / (-b))) + cx));

                    bool lr4 = (col < (((a) * (1 - (row - cy) / (b))) + cx));

                    inFlag = (!lr1 && !lr2 && lr3 && lr4);

                }

            }

            if (shapeType == cstPlus) { // 加号

                inFlag =

                    (fabs(cx - startX) > fabs(cx - col) || fabs(cy - startY) >

                    fabs(cy - row));

            }

            *pDst++ = (inFlag != (zoomType == csdZoomOut) ? 0 : 255);

        }

}

// ***************************** 形状效果 **************************************

 

// ***************************** 轮子效果 **************************************

__fastcall TCbwAnimationEffect_Wheel::TCbwAnimationEffect_Wheel()

    : TCbwAnimationEffect() {

    EffectType = cetWheel;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_Wheel::Build() {

    return new TCbwAnimationEffect_Wheel;

}

 

void __fastcall TCbwAnimationEffect_Wheel::BuildMaskMat(cv::Mat& destMat,

    cv::Mat& srcMat, TRect displayRect) {

    bool clockwiseFlag = (MyOptionType.Items[1].CurrentValue == 0); // 方向

    int pattern = MyOptionType.Items[2].CurrentValue + 1; // 轮辐图案

    if (pattern == 5)

        pattern = 8;

    TRect wholeRect(0, 0, displayRect.right - displayRect.left,

        displayRect.bottom - displayRect.top);

    double cx = wholeRect.right / 2.0, cy = wholeRect.bottom / 2.0;

    TCbwFloatPoint centerPoint(cx, cy);

 

    double unitDegree = 360 / pattern;

    double deltaDegree = double(FCurrentIndex + 1) / FPeriodLength * unitDegree;

    BYTE * pSrc = srcMat.data;

    BYTE * pDst = destMat.data;

    for (int row = 0; row < destMat.rows; ++row)

        for (int col = 0; col < destMat.cols; ++col) {

            TCbwFloatPoint p(col, row);

            double theta = p.ThetaToPoint(centerPoint);

            if (clockwiseFlag)

                theta = 360 - theta;

            bool inFlag = false;

            for (int i = 0; i < pattern; ++i) {

                if (theta >= unitDegree * i && (theta - unitDegree * i) <=

                    deltaDegree)

                    inFlag = true;

            }

            *pDst++ = inFlag ? 255 : 0;

        }

}

// ***************************** 轮子效果 **************************************

 

// ***************************** 随机线效果 **************************************

__fastcall TCbwAnimationEffect_RandomLine::TCbwAnimationEffect_RandomLine()

    : TCbwAnimationEffect() {

    EffectType = cetRandomLine;

    FOccurredLines = NULL;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_RandomLine::Build() {

    return new TCbwAnimationEffect_RandomLine;

}

 

void __fastcall TCbwAnimationEffect_RandomLine::BuildMaskMat(cv::Mat& destMat,

    cv::Mat& srcMat, TRect displayRect) {

    bool horzFlag = (MyOptionType.Items[1].CurrentValue == 0); // 方向

    TRect wholeRect(0, 0, displayRect.right - displayRect.left,

        displayRect.bottom - displayRect.top);

    int totalLineNumber = (horzFlag ? wholeRect.bottom : wholeRect.right);

    int number = double(FCurrentIndex + 1) / FPeriodLength * totalLineNumber;

    if (!FOccurredLines) {

        FOccurredLines = new BYTE[totalLineNumber];

        ZeroMemory(FOccurredLines, totalLineNumber);

    }

    int destNumber =

        number -int(double(FCurrentIndex) / FPeriodLength * totalLineNumber);

    BYTE * pSrc = srcMat.data;

    BYTE * pDst = destMat.data;

    vector<int>totalLines;

    for (int i = 0; i < totalLineNumber; ++i)

        totalLines.push_back(i);

    while (destNumber-- > 0 && totalLines.size()) {

        int n = random(totalLines.size());

        while (FOccurredLines[totalLines[n]]) {

            totalLines.erase(totalLines.begin() + n);

            n = random(totalLines.size());

        }

        FOccurredLines[totalLines[n]] = 1;

        totalLines.erase(totalLines.begin() + n);

    }

    for (int row = 0; row < destMat.rows; ++row)

        for (int col = 0; col < destMat.cols; ++col) {

            bool inFlag = (horzFlag ? FOccurredLines[row] :

                FOccurredLines[col]);

            *pDst++ = inFlag ? 255 : 0;

        }

    if (FCurrentIndex == FPeriodLength - 1) {

        delete FOccurredLines;

        FOccurredLines = NULL;

    }

}

// ***************************** 随机线效果 **************************************

 

// ***************************** 翻转式由远及近效果 **************************************

__fastcall TCbwAnimationEffect_RotateToNear::TCbwAnimationEffect_RotateToNear()

    : TCbwAnimationEffect_SameMask() {

    EffectType = cetRotateToNear;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_RotateToNear::Build() {

    return new TCbwAnimationEffect_RotateToNear;

}

 

void __fastcall TCbwAnimationEffect_RotateToNear::BuildDisplayMat

    (cv::Mat& destMat, cv::Mat& srcMat, TRect displayRect) {

    bool clockwiseFlag = (MyOptionType.Items[1].CurrentValue == 0); // 顺时针

    cv::Point2f center = cv::Point2f(srcMat.cols / 2, srcMat.rows / 2); // 旋转中心

    double angle = -45 * (1-double(FCurrentIndex + 1) / FPeriodLength); // 旋转角度

    if (clockwiseFlag)

        angle *= -1;

    double scale = 0.5 * (1+double(FCurrentIndex + 1) / FPeriodLength); // 缩放尺度

    cv::Mat rotateMat = cv::getRotationMatrix2D(center, angle, scale);

    cv::warpAffine(srcMat, destMat, rotateMat, srcMat.size());

}

 

// ***************************** 翻转式由远及近效果 **************************************

 

// ***************************** 缩放效果 **************************************

__fastcall TCbwAnimationEffect_Zoom::TCbwAnimationEffect_Zoom()

    : TCbwAnimationEffect_SameMask() {

    EffectType = cetZoomEffect;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_Zoom::Build() {

    return new TCbwAnimationEffect_Zoom;

}

 

void __fastcall TCbwAnimationEffect_Zoom::BuildDisplayMat(cv::Mat& destMat,

    cv::Mat& srcMat, TRect displayRect) {

    bool clockwiseFlag = (MyOptionType.Items[1].CurrentValue == 0); // 顺时针

    cv::Point2f center = cv::Point2f(srcMat.cols / 2, srcMat.rows / 2); // 旋转中心

    double scale = 0.5 * (1+double(FCurrentIndex + 1) / FPeriodLength); // 缩放尺度

    cv::Mat rotateMat = cv::getRotationMatrix2D(center, 0, scale);

    cv::warpAffine(srcMat, destMat, rotateMat, srcMat.size());

}

 

// ***************************** 缩放效果 **************************************

 

// ***************************** 旋转效果 **************************************

__fastcall TCbwAnimationEffect_Rotate::TCbwAnimationEffect_Rotate()

    : TCbwAnimationEffect_SameMask() {

    EffectType = cetRotateEffect;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_Rotate::Build() {

    return new TCbwAnimationEffect_Rotate;

}

 

void __fastcall TCbwAnimationEffect_Rotate::BuildDisplayMat(cv::Mat& destMat,

    cv::Mat& srcMat, TRect displayRect) {

    bool horzFlag = (MyOptionType.Items[1].CurrentValue == 0); // 方向

    double periodLength = FPeriodLength / 2.0;

    double value = (FCurrentIndex + 1) / periodLength;

    int segment = value;

    value -= int(value);

    double scale = fabs(value - 0.5) * 2;

    int cols = srcMat.cols * scale, rows = srcMat.rows;

    if (!horzFlag) {

        cols = srcMat.cols;

        rows = srcMat.rows * scale;

    }

    if (cols == 0 || rows == 0)

        return;

    cv::Mat partMat = destMat(cv::Rect((destMat.cols - cols) / 2,

        (destMat.rows - rows) / 2, cols, rows));

    cv::Size dsize = cv::Size(cols, rows);

    resize(srcMat, partMat, dsize);

    if (value > 0.5 != (segment % 2))

        flip(partMat, partMat, horzFlag ? 1 : 0);

}

// ***************************** 旋转效果 **************************************

 

// ***************************** 弹跳效果 **************************************

__fastcall TCbwAnimationEffect_Bounce::TCbwAnimationEffect_Bounce()

    : TCbwAnimationEffect() {

    EffectType = cetBounce;

}

 

TCbwAnimationEffect * TCbwAnimationEffect_Bounce::Build() {

    return new TCbwAnimationEffect_Bounce;

}

 

TRect __fastcall TCbwAnimationEffect_Bounce::BuildDisplayRect(OBJECTMAT * m) {

    double x = double(FCurrentIndex + 1) / FPeriodLength;

    double v = sin((x - 1) * 3 * PI);

 

    double y = fabs(200 * v / exp(0.3 * (x - 1)));

    y = m->LeftTopPosition.y - y;

    x = m->LeftTopPosition.x + (x - 1) * 500;

    TRect result(x, y, x + m->Mat.cols, y + m->Mat.rows);

    return result;

}

 

// ***************************** 弹跳效果 **************************************

 

配置:

 

图标

 

实现完成后,发现弹跳的效果没有达到预期。

 

先解决有问题,先完成,再完善。

 

本周按计划完成PPT动画效果框架设计与实现。年也过完了,下周把电子黑板的功能更上一层楼。

posted on 2015-03-06 16:04  drgraph  阅读(569)  评论(0编辑  收藏  举报