查看原文
其他

画线纹理之绳子!

lamyoung 白玉无冰 2022-06-10

为绳子任意方向的拖动添加纹理~

效果预览

前置教程

这次的纹理是使用 Sprite 组件的渲染模式 Mesh ,前文 初探精灵中的网格渲染模式 ! 介绍了这个用法。

绘制的数据要用到 _poins 来画长方形,前文 画线纹理之简单实现 中有介绍。

在连接处画个圆达到平衡效果,前文 画线纹理之连接优化 中有讲到处理方法。

回顾一下这三篇文章有助于本文的理解哦~

实现原理

前几篇已经实现了画线纹理,这次主要的目标是计算正确的 uv 坐标。

因为这个线有方向,有长度,都会影响纹理坐标的计算。

这里想到的一个思路是,把所有的线段拉成一条直线,并放到一个方向

为了使这个纹理能从尾部带动头部的效果,拉直后,最后一个点作为纹理的起始点。

所以遍历这个点的时候,要从尾部开始,并记录一下每节的长度。

纹理坐标 v 的两个点是 01 。纹理坐标 u (水平方向) 根据绳子的长度去推算。

// 从最后一点开始计算
for (let index2 = pathPoints.length - 1; index2 > 0; index2--) {
 // 省略部分代码
 vertices.x.push(p_r_t.x, p_r_b.x, p_l_t.x, p_l_b.x);
 vertices.y.push(p_r_t.y, p_r_b.y, p_l_t.y, p_l_b.y);
    // 计算uv
 vertices.nu.push(offsetX.x * uv_mul, offsetX.x * uv_mul, (offsetX.x + dirLen) * uv_mul, (offsetX.x + dirLen) * uv_mul);
 vertices.nv.push(1010);
 // 省略部分代码
 offsetX.addSelf(cc.v2(dirLen, 0)); // 记录已经画的长度长度
}

这么倒着遍历会出现一个问题,就是尾巴的纹理会被头覆盖。

所以计算长方形的顶点索引后,要整体反转,让他从头开始画。主要代码如下。

let trianglesCache: number[][] = [];
for (let index2 = pathPoints.length - 1; index2 > 0; index2--) {
    // 省略部分代码
    triangles.push(i_offset + 0);
    triangles.push(i_offset + 1);
    triangles.push(i_offset + 2);
    triangles.push(i_offset + 1);
    triangles.push(i_offset + 2);
    triangles.push(i_offset + 3);
    trianglesCache.push(triangles);

trianglesCache.reverse(); // 顶点索引反转
trianglesCache.forEach(v => {
 // 真正的顶点索引顺序
    vertices.triangles.push(...v)
})

反转后,绳子的纹理就正确了。

对于连接处画圆(实际是多边形),需要注意每个点都要旋转,这样才能让圆的纹理方向正确。

参考代码如下。

//画圆
const dir_angle = dir.signAngle(cc.v2(-10));//与x轴的负方向的夹角
const count = 12;
i_offset = vertices.x.length;
// 这里是圆心
vertices.x.push(p.x);
vertices.y.push(p.y);
vertices.nu.push(offsetX.x * uv_mul);
vertices.nv.push(0.5);
for (let index3 = 0; index3 < count; index3++) {
    const r = 2 * Math.PI * index3 / count;
    // 圆心到各个边的向量
    const pos_circle = cc.v2(w / 2 * Math.cos(r), w / 2 * Math.sin(r));
    vertices.x.push(pos_circle.add(p).x);
    vertices.y.push(pos_circle.add(p).y);
    // 对于圆的uv需要旋转
    vertices.nu.push((pos_circle.rotate(dir_angle).x + offsetX.x) * uv_mul);
    vertices.nv.push(pos_circle.rotate(dir_angle).y / w + 0.5);
    if (index3 === 0) {
        triangles.push(i_offset, i_offset + 1 + index3, i_offset + count);
    } else {
        triangles.push(i_offset, i_offset + 1 + index3, i_offset + index3);
    }
}

最后,给大家画个星吧~

小结

这个绳子纹理的整个思路就是把所有弯的线,都转化成直的后,再计算纹理坐标。

以上为白玉无冰使用 Cocos Creator v2.3.3 关于 "画线纹理之绳子!" 的技术分享。如果对你有点帮助,欢迎分享给身边的朋友。




2019年第一季度原创精选整理     图片/文字 的渐变色实现!   画线纹理之连接优化

物理挖洞之 3D !  初探精灵中的网格渲染模式 !  画线纹理的一种简单实现!

物理流体的一种实现!  原创专辑整理    shader入门实战资料整理 !

转载请保留文末二维码和完整代码获取方式!

完整代码(详见readme): https://github.com/baiyuwubing

点击“阅读原文”查看精选导航

“在看”是最大的鼓励▼

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存