最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 折纸效果! Cocos Creator 3.0

    正文概述 掘金(白玉无冰)   2021-05-01   625

    效果

    折纸效果! Cocos Creator 3.0

    实现

    整体思路

    思路遵循以下几步

    • 初始化一个多边形。
    • 折叠后分割成两个多边形。
    • 如果需要继续分割,对场上的所有多边形进行折叠,折叠出新的多边形的层级正好与原来的相反。

    折纸效果! Cocos Creator 3.0

    所以,所有的计算和渲染都可以转换成对一个多边形的操作。

    为了简化计算,我们约定初始化的多边形为凸多边形。这么做有几个好处。

    • 折叠后生成的仍是凸多边形,并且对于每个多边形只会折叠出两个
    • 渲染时,分割凸多边形为三角形特别方便,即能快速计算出顶点索引

    计算

    主要分为三块

    • 多边形分割
    • 线线交点
    • 轴对称

    分割

    观察触摸方向和多边形各个点的关系。

    可以发现,触摸方向触摸方向中点指向多边形顶点 的夹角决定了分割后的多边形的点。

    折纸效果! Cocos Creator 3.0

    • 当夹角大于90度时,该顶点正好是折叠多边形的顶点。
    • 当夹角等于90度时,该顶点是两个多边形的顶点。
    • 当夹角小于90度时,该顶点是底部多边形的顶点。

    向量间的点积正好可以帮助我们判断夹角问题。

    const dotValue = temp_v2_vector.dot(temp_v2_vector_3)
    if (Math.abs(dotValue) === 0) {
        // 刚好在点上      
    } else if (dotValue > 0) {
        // 在前面  
    } else {
        // 在后面
    }
    

    交点

    当被分割的多边形相邻两点与触摸方向的夹角不同时(属于两个多边形的点),需要计算触摸向量的垂直线与该线段的交点。

    折纸效果! Cocos Creator 3.0

    直线上的一点可以用点和向量表示。

    折纸效果! Cocos Creator 3.0

    把两直线的点表达式结合,再运用克莱姆法则(Cramer's Rule)求出交点。

    折纸效果! Cocos Creator 3.0

    function linelinePoint(p1: Vec2, p1Dir: Vec2, p2: Vec2, p2Dir: Vec2) {
        const a1 = p1Dir.x, b1 = -p2Dir.x, c1 = p2.x - p1.x
        const a2 = p1Dir.y, b2 = -p2Dir.y, c2 = p2.y - p1.y
        const d = a1 * b2 - a2 * b1,
            d1 = c1 * b2 - c2 * b1,
            d2 = a1 * c2 - c1 * a2
        const t1 = d1 / d, t2 = d2 / d
        return [t1, t2]
    }
    

    这里计算的是比例t,这个t不仅可以用来求出顶点坐标,也可以求出相交的纹理坐标。

    const posSpilt = Vec2(pos.x + dir.x * t1, pos.y + dir.y * t1)
    const uvSpilt = Vec2(uv.x + uvdir.x * t1, uv.y + uvdir.y * t1)
    

    对称点

    折叠多边形的顶点正好是原多边形顶点关于触摸垂直轴对称的点。

    折纸效果! Cocos Creator 3.0

    求对称点同样可以运用向量计算。

    1. 求出该顶点与中点的向量
    2. 求出该点在触摸方向的单位向量的投影(点乘),这正好是距离的一半
    3. 求出对称点坐标(距离乘方向向量+起始点坐标)

    折纸效果! Cocos Creator 3.0

    Vec2.subtract(temp_v2_vector_4, temp_v2_pos, pos)
    const dotLength = temp_v2_vector_4.dot(temp_v2_vector) * 2
    temp_v2_pos_2.set((pos.x + temp_v2_vector.x * dotLength), pos.y + temp_v2_vector.y * dotLength)
    

    渲染

    渲染一个图形一般是由三角形组成。

    对于凸多边形,分割三角形就比较简单。选取其中一个顶点,和其他顶点连接,就可以把多边形分割成三角形。

    折纸效果! Cocos Creator 3.0

    渲染一个凸多边形采用Assembler的方式组装顶点数据。

    分为以下几步实现:

    1. 将引擎中的Sprite-simple组装器拷贝出来,作为自己的组装器模板。
    2. 新建一个类继承Sprite,并设置它的组装器到自己的组装器
    3. 创建变量顶点数组,纹理数组。
    4. 编写组装器逻辑

    直接看看代码吧:D

    凸多边形的类。

    // 仅限凸多边形
    @ccclass('PolygonSprite')
    export class PolygonSprite extends Sprite {
        @property({ type: [Vec2] })
        protected _vertices: Vec2[] = [new Vec2(-100, -100), new Vec2(100, -100), new Vec2(100, 100), new Vec2(-100, 100)];
        // 省略部分代码
    
        @property({ type: [Vec2] })
        protected _uvs: Vec2[] = [new Vec2(0, 0), new Vec2(1, 0), new Vec2(1, 1), new Vec2(0, 1)];
        // 省略部分代码
    
        protected _flushAssembler() {
            //指向自定义的组装器
            let assembler = polygonAssembler;
            if (this._assembler !== assembler) {
                this.destroyRenderData();
                this._assembler = assembler;
            }
            // 省略部分代码
        }
    }
    

    接下来看组装器内修改部分。

    处理顶点数据

    // 保存顶点数据
    updateVertexData(sprite: PolygonSprite) {
        //中间变量
        const renderData = sprite.renderData;
        if (!renderData) {
            return;
        }
        renderData.vertexCount = renderData.dataLength = sprite.vertices.length
        // 三角形数量 = 顶点数 - 2
        // 索引数量 = 三角形数量X3
        renderData.indicesCount = (renderData.vertexCount - 2) * 3
        renderData.vertDirty = false;
        for (let i = 0; i < sprite.vertices.length; ++i) {
            const xy = sprite.vertices[i];
            renderData.data[i].x = xy.x
            renderData.data[i].y = xy.y
        }
    },
    

    缓存UV坐标,我们定义的纹理坐标是归一化到0-1,在更新数据时再根据实际的纹理坐标(合图)进行转换。

    updateUvs(sprite: PolygonSprite) {
        const renderData = sprite.renderData!;
        //实际uv
        const uv = sprite.spriteFrame!.uv;
        // 左 下 上 右 
        const l = uv[0], b = uv[1], t = uv[7], r = uv[6]
        for (let i = 0; i < sprite.uvs.length; ++i) {
            const uvs = sprite.uvs[i];
            renderData.data[i].u = l + (r - l) * uvs.x
            renderData.data[i].v = b + (t - b) * uvs.y
        }
        renderData.uvDirty = false;
    },
    

    填充数据修改,顶点索引就从第一个点开始连接到各个顶点的三角形。

    fillBuffers(sprite: PolygonSprite, renderer: any) {
        //省略代码
    
        // 填充顶点
        for (let i = 0; i < renderData.vertexCount; ++i) {
            const vert = renderData.data[i];
            // 计算世界坐标
            vBuf![vertexOffset++] = a * vert.x + c * vert.y + tx;
            vBuf![vertexOffset++] = b * vert.x + d * vert.y + ty;
            vBuf![vertexOffset++] = vert.z;
            // 填充uv
            vBuf![vertexOffset++] = vert.u;
            vBuf![vertexOffset++] = vert.v;
            Color.toArray(vBuf!, sprite.color, vertexOffset);
            vertexOffset += 4;
        }
    
        // 填充索引
        for (let i = 0; i < sprite.vertices.length - 2; ++i) {
            const start = i;
            iBuf![indicesOffset++] = vertexId;
            iBuf![indicesOffset++] = start + 1 + vertexId;
            iBuf![indicesOffset++] = start + 2 + vertexId;
        }
    },
    

    小结

    实现折叠效果可以将问题分解成处理一个多边形的问题,并用assembler实现合批渲染。

    以上为白玉无冰使用 Cocos Creator 3.0.0 实现 "折纸效果!" 的技术分享。欢迎三连(点赞/在看/留言/分享)支持!

    完整项目链接 - cocos store (100分)

    当然也可以在号内找到所有教程项目的地址:D
    原文链接


    起源地下载网 » 折纸效果! Cocos Creator 3.0

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元