提交一份mesh的学习笔记吧

首先,感谢两位大佬的教学,学习两位大佬的技术让我知道了顶点是怎么回事,该怎么操作,大佬地址直通车:



我是用的精灵的mesh渲染模式做的切割来玩的,然后我调整了切割份数后发现,意外形成了爆炸烟雾类的效果
测试代码:
const {ccclass, property} = cc._decorator;
const time_scale = 1; // 动画速度 <0为慢,>0为快
const w = 544;
const h = 544;
@ccclass
export default class TestScene extends cc.Component {
@property(cc.Sprite)
mesh: cc.Sprite = null;
private isMesh: boolean = false;private verts = {
x:[],
y:[],
nv:[],
nu:[],
triangles:[]
};
private initVerts = {
x:[],
y:[],
nv:[],
nu:[],
triangles:[]
}
private mper: number = 0;
private speed: number = 1;
private playBoom: boolean = false;
onLoad () {
this.initMeshVerts();
}

handleBtnMeshTest () {
    if (this.isMesh) return;
    this.mper = 0;
    this.isMesh = true;
}

pushVerts (x, y) {
    this.initVerts.x.push(x);
    this.initVerts.y.push(y);
    this.initVerts.nu.push(x/w);
    this.initVerts.nv.push(y/h);
    this.initVerts.triangles.push(this.initVerts.x.length-1);
}

initMeshVerts () {
    let count = 100;  // 均分

    if (this.initVerts.x.length === 0) {
        for (let c=0; c<count; ++c) {
            for (let r=0; r<count; ++r) {
                for (let d=0; d<2; ++d) {   //上下
                    let x = r * w / count;
                    let y = c * h / count;
                    this.pushVerts(x, y);
                    this.pushVerts(x + w / count, y + h / count);
                    if (d === 0) {
                        this.pushVerts(x + w / count, y);
                    } else {
                        this.pushVerts(x, y + h / count);
                    }
                }
            }
        }
    }

    this.cloneVerts(this.verts, this.initVerts);
    let c = cc.v2(w/2, h/2);    // 扩散圆心
    let radius = h  // 最大扩散半径

    for (let i=0; i<this.verts.triangles.length; i+=3) {
        let v:cc.Vec2[] = [];
        for (let c=0; c<3; ++c) {
            let id = this.verts.triangles[c + i];
            let p = cc.v2(this.verts.x[id], this.verts.y[id]);
            v.push(p);
        }
        let center = this.getPolygonCenter(v);
        let rr, ra; // 随机半径,随机度数
        let tv; // 目标点

        rr = Math.random() * radius;
        ra = Math.random() * 2 * Math.PI;
        tv = cc.v2(rr * Math.cos(ra), rr * Math.sin(ra)).add(c);

        let dir = center.sub(tv);

        v.forEach((_v:cc.Vec2, index)=>{
            let nv = _v.sub(dir);
            let id = this.verts.triangles[index + i];
            this.verts.x[id] = nv.x;
            this.verts.y[id] = nv.y;
        });
    }

    //@ts-ignore
    this.mesh.spriteFrame.vertices = this.playBoom ? this.initVerts : this.verts;
    //@ts-ignore
    this.mesh.setVertsDirty();
}

getPolygonCenter (verts:cc.Vec2[]):cc.Vec2 {
    let x=0, y=0;
    verts.forEach(v=>{
        x += v.x;
        y += v.y;
    })
    x /= verts.length;
    y /= verts.length;
    return cc.v2(x, y);
}

cloneVerts (v1, v2) {
    v1.x = v2.x.slice();
    v1.y = v2.y.slice();
    v1.nv = v2.nv.slice();
    v1.nu = v2.nu.slice();
    v1.triangles = v2.triangles.slice();
}

updateMeshVerts () {
    let nverts = {
        x:[],
        y:[],
        nv:[],
        nu:[],
        triangles:[]
    };
    this.cloneVerts(nverts, this.playBoom ? this.initVerts : this.verts);
    let tverts = this.playBoom ? this.verts : this.initVerts;
    for (let i=0; i<nverts.triangles.length; i+=3) {
        let v:cc.Vec2[] = [];
        let iv:cc.Vec2[] = [];
        for (let c=0; c<3; ++c) {
            let id = nverts.triangles[c + i];
            let p = cc.v2(nverts.x[id], nverts.y[id]);
            v.push(p);

            id = tverts.triangles[c + i];
            p = cc.v2(tverts.x[id], tverts.y[id]);
            iv.push(p);
        }
        let icenter = this.getPolygonCenter(iv);
        let center = this.getPolygonCenter(v);
        let dir = center.sub(icenter).mul(this.mper);

        v.forEach((_v:cc.Vec2, index)=>{
            let nv = _v.sub(dir);
            let id = nverts.triangles[index + i];
            nverts.x[id] = nv.x;
            nverts.y[id] = nv.y;
        });
    }

    //@ts-ignore
    this.mesh.spriteFrame.vertices = nverts;
    //@ts-ignore
    this.mesh.setVertsDirty();
}

update (dt) {
    dt *= time_scale;

    if (this.isMesh) {
        this.mper += dt * this.speed * (this.playBoom ? 10 : 1);
        if (this.mper >= 1) {
            this.mper = 1;
        }
        this.updateMeshVerts();
        if (this.mper >= 1) {
            this.isMeshOpen = !this.playBoom;
            this.playBoom = !this.playBoom;
            this.isMesh = false;
        }
    }
}

}

2赞

补充一个白玉无冰大佬的bug(可能是当时他用的那个版本问题吧,我这版本是2.4.2):sprite的mesh模式不强制需要打成图集,当然图集可以方便做更多效果,只要你会算uv坐标

大佬,跑不起來0.0

我就只放一份代码,肯定跑不了,你得自己加工程然后弄弄按钮、精灵啥的

都加了,CCSpriteframe报错了,this.mesh.spriteFrame.vertices ,vertices 属性里面少了 u,v

你啥版本的?我2.4.2的,用的是nu和nv


2.3.4和2.4.3都有这一段代码

你是不是精灵没有放图片?精灵上需要放一张图片的

放了的。。。没图片怎么跑。。。你断点到这个位置看看,有没有这个属性0.0

是克利波 爱了

刚断点看了下,程序运行中没有进这个方法,只在进入场景加载资源的时候走_setDynamicAtlasFrame进来了,应该是静态加载图片的时候计算的,这块uv我猜测是默认的图的uv计算

emm…这张图也是拿得论坛里某个大佬的工程里的图,好像是学shader的时候拿的,忘记了,手上没图了就随便拿来用的

是的,场景加载的时候就进入到这里面了,然后提示报错了

我刚去改了下,在let vertices = this.vertices;下加了个打印,发现vertices是undefined


是不是精灵设置问题?type需要设置成MESH模式

是的,大佬牛逼!

能跑就好,我也是初学者,在找大佬们的教程学

用的那张图,如果不勾pakeable就会显示其他用到的图,如果勾了,尺寸就不一样
image


这是什么原因啊0.0

应该是勾了才会用到其他图吧?主要是nv、nu那里,我是按单张图计算的。然后拉伸比率这个我在最上面有个const w、h是图片尺寸,是写死的需要自己改一下,或者弄成获取精灵尺寸也行

感谢,受教了!