zoukankan      html  css  js  c++  java
  • cocos2dx 仿射变换

    AffineTransform __CCAffineTransformMake(float a, float b, float c, float d, float tx, float ty)
    {
      AffineTransform t;
      t.a = a; t.b = b; t.c = c; t.d = d; t.tx = tx; t.ty = ty;
      return t;
    }
    
    Vec2 __CCPointApplyAffineTransform(const Vec2& point, const AffineTransform& t)
    {
      Vec2 p;
      p.x = (float)((double)t.a * point.x + (double)t.c * point.y + t.tx);
      p.y = (float)((double)t.b * point.x + (double)t.d * point.y + t.ty);
      return p;
    }
    
    Vec2 PointApplyTransform(const Vec2& point, const Mat4& transform)
    {
        Vec3 vec(point.x, point.y, 0);
        transform.transformPoint(&vec);
        return Vec2(vec.x, vec.y);
    }
    
    
    Size __CCSizeApplyAffineTransform(const Size& size, const AffineTransform& t)
    {
      Size s;
      s.width = (float)((double)t.a * size.width + (double)t.c * size.height);
      s.height = (float)((double)t.b * size.width + (double)t.d * size.height);
      return s;
    }
    
    
    AffineTransform AffineTransformMakeIdentity()
    {
        return __CCAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
    }
    
    extern const AffineTransform AffineTransformIdentity = AffineTransformMakeIdentity();
    const AffineTransform AffineTransform::IDENTITY = AffineTransformMakeIdentity();
    
    //获取仿射变换转换之后的坐标
    Rect RectApplyAffineTransform(const Rect& rect, const AffineTransform& anAffineTransform)
    {
        //四个最值
        float top    = rect.getMinY();  //左上角Y
        float left   = rect.getMinX();  //左上角X
        float right  = rect.getMaxX();  //右下角X
        float bottom = rect.getMaxY();  //右下角Y
        
        //四个顶点坐标
        Vec2 topLeft = PointApplyAffineTransform(Vec2(left, top), anAffineTransform); //左上角
        Vec2 topRight = PointApplyAffineTransform(Vec2(right, top), anAffineTransform); //右上角
        Vec2 bottomLeft = PointApplyAffineTransform(Vec2(left, bottom), anAffineTransform); //左下角
        Vec2 bottomRight = PointApplyAffineTransform(Vec2(right, bottom), anAffineTransform); //右下角
    
        //找到可以承载这个矩形的最大正矩形坐标
        float minX = min(min(topLeft.x, topRight.x), min(bottomLeft.x, bottomRight.x));
        float maxX = max(max(topLeft.x, topRight.x), max(bottomLeft.x, bottomRight.x));
        float minY = min(min(topLeft.y, topRight.y), min(bottomLeft.y, bottomRight.y));
        float maxY = max(max(topLeft.y, topRight.y), max(bottomLeft.y, bottomRight.y));
        
        //返回可容纳最大矩形的Rect
        return Rect(minX, minY, (maxX - minX), (maxY - minY));
    }
    
    //直接获取坐标
    Rect RectApplyTransform(const Rect& rect, const Mat4& transform)
    {
        //四个最值
        float top    = rect.getMinY();
        float left   = rect.getMinX();
        float right  = rect.getMaxX();
        float bottom = rect.getMaxY();
        
        //四个顶点坐标
        Vec3 topLeft(left, top, 0);
        Vec3 topRight(right, top, 0);
        Vec3 bottomLeft(left, bottom, 0);
        Vec3 bottomRight(right, bottom, 0);
        transform.transformPoint(&topLeft);
        transform.transformPoint(&topRight);
        transform.transformPoint(&bottomLeft);
        transform.transformPoint(&bottomRight);
    
        //获取四个最值点
        float minX = min(min(topLeft.x, topRight.x), min(bottomLeft.x, bottomRight.x));
        float maxX = max(max(topLeft.x, topRight.x), max(bottomLeft.x, bottomRight.x));
        float minY = min(min(topLeft.y, topRight.y), min(bottomLeft.y, bottomRight.y));
        float maxY = max(max(topLeft.y, topRight.y), max(bottomLeft.y, bottomRight.y));
    
        //返会可容纳的最大矩形
        return Rect(minX, minY, (maxX - minX), (maxY - minY));
    }
    
    //         [ 1  0  0 ]
    //[x y 1]* [ 0  1  0 ]
    //         [ tx ty 1 ]
    //平移到(x+tx, y+ty, 1)
    AffineTransform AffineTransformTranslate(const AffineTransform& t, float tx, float ty)
    {
        return __CCAffineTransformMake(t.a, t.b, t.c, t.d, t.tx + t.a * tx + t.c * ty, t.ty + t.b * tx + t.d * ty);
    }
    
    //         [ a*sx  0     0 ]
    //[x y 1]* [ 0     d*sy  0 ]
    //         [ 0     0     1 ]
    //x坐标缩放sx倍,y坐标缩放sy倍
    AffineTransform AffineTransformScale(const AffineTransform& t, float sx, float sy)
    {
        return __CCAffineTransformMake(t.a * sx, t.b * sx, t.c * sy, t.d * sy, t.tx, t.ty);
    }
    
    //         [ cosa   sina  0 ]
    //[x y 1]* [ -sina  cosa  0 ]
    //         [ 0      0     1 ]
    //旋转
    AffineTransform AffineTransformRotate(const AffineTransform& t, float anAngle)
    {
        float sine = sinf(anAngle);
        float cosine = cosf(anAngle);
    
        return __CCAffineTransformMake( t.a * cosine + t.c * sine,
                                        t.b * cosine + t.d * sine,
                                        t.c * cosine - t.a * sine,
                                        t.d * cosine - t.b * sine,
                                        t.tx,
                                        t.ty);
    }
    
    //将两个矩阵相乘 得到第二个矩阵的xy轴在第一个矩阵xy轴上的投影
    //下面的参数化简完就变成了
    //[ a1*a2 0     0 ]
    //[ 0     d1*d2 0 ]
    //[ 0     0     0 ]
    /* Concatenate `t2' to `t1' and return the result:
         t' = t1 * t2 */
    AffineTransform AffineTransformConcat(const AffineTransform& t1, const AffineTransform& t2)
    {
        return __CCAffineTransformMake( t1.a * t2.a + t1.b * t2.c, t1.a * t2.b + t1.b * t2.d, //a,b
                                        t1.c * t2.a + t1.d * t2.c, t1.c * t2.b + t1.d * t2.d, //c,d
                                        t1.tx * t2.a + t1.ty * t2.c + t2.tx,                  //tx
                                        t1.tx * t2.b + t1.ty * t2.d + t2.ty);                 //ty
    }
    
    Mat4 TransformConcat(const Mat4& t1, const Mat4& t2)
    {
        return t1 * t2;
    }
    
    //
    /* Return true if `t1' and `t2' are equal, false otherwise. */
    bool AffineTransformEqualToTransform(const AffineTransform& t1, const AffineTransform& t2)
    {
        return (t1.a == t2.a && t1.b == t2.b && t1.c == t2.c && t1.d == t2.d && t1.tx == t2.tx && t1.ty == t2.ty);
    }
    
    //交换xy轴的值
    //转换为
    //[ d 0 0 ]
    //[ 0 a 0 ]
    //[ 0 0 0 ]
    AffineTransform AffineTransformInvert(const AffineTransform& t)
    {
        float determinant = 1 / (t.a * t.d - t.b * t.c);
    
        return __CCAffineTransformMake(determinant * t.d, -determinant * t.b, -determinant * t.c, determinant * t.a,
                                determinant * (t.c * t.ty - t.d * t.tx), determinant * (t.b * t.tx - t.a * t.ty) );
    }
    
    NS_CC_END
    
    

    如果不明白为什么一些原理,比如tx=ty=0,可以看一下下面这篇文章,有很细致的讲解,我这个是只是对代码的解读。
    仿射变换几何讲解

  • 相关阅读:
    PHP中读写文件
    Java和PHP在Web开发方面的比较
    CentOS yum安装 Apache + PHP + MySQL
    PHP 时间参数大全
    数据库结果太大,PHP超出内存限制
    PHP扩展配置?
    php 实现KMP算法
    OS + Linux Shell bash / sh / ksh / csh / tcsh / adb shell
    my soft / text tools / EmEditor / Notepad++ / UltraEdit / EditPlus / Sublime Text
    JAVA EE Projects_sourceforge
  • 原文地址:https://www.cnblogs.com/sakuraneo/p/11992052.html
Copyright © 2011-2022 走看看