使用 mesh 實現多邊形裁剪圖片!Cocos Creator!


和 mask 裁剪圖片說拜拜,用上高性能的 mesh + shader 。文章底部獲取完整代碼!

效果預覽:

使用方法:

  1. 創建一個空節點
  2. 添加用戶腳本組件 mesh-texture-mask
  3. 添加圖片
  4. 添加修改多邊形頂點坐標

實現原理

創建 mesh

mesh 是什么? mesh 是決定一個物體形狀的東西。 例如在二維中可以是正方形、圓形、三角形等;在三維中可以是正方體、球體、圓柱體等。

mesh 初始化需要一個 VertexFormat 對象。這個對象是頂點格式對象。

其中 name 是對應頂點着色器的 attribute 變量的值。 type 對應數據類型,決定了每個數據大小。

num 對應有幾個數據分量(猜的哈哈!)。例如二維坐標和紋理uv坐標一般只有xy兩個分量,所以設置為2;三維坐標有xyz三個變量,所以值為3;而顏色一般有 rgba 四個分量,所以設置為4。

normalize 表示歸一化。

對於我們的多邊形裁剪圖片,只需要一個二維坐標和一個紋理uv坐標,創建 mesh 參考代碼如下:

const gfx = cc.gfx;
let mesh = new cc.Mesh();
mesh.init(new gfx.VertexFormat([
    { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
    { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
]), this.vertexes.length, true);

計算紋理uv坐標

紋理uv坐標系在左上角,u軸是向右,v軸是向下,范圍是 0~1。而我們的坐標系在中間,x軸向右,y軸向上。

所以我們可以先求出x,y在左下角的占比,然后再反轉一下y軸,轉成uv坐標系。參考代碼如下。

const vx = (pt.x + this.texture.width / 2 + this.offset.x) / this.texture.width;
const vy = 1.0 - (pt.y + this.texture.height / 2 + this.offset.y) / this.texture.height;

計算頂點索引

首先需要知道一個概念,繪制一個形狀實際上是繪制多個三角形。一個多邊形可以分割成多個三角形,而頂點索引是告訴它如何去繪制這些三角形。

如何將一個多邊形切割成多個三角形?可以采用'耳切法'的方式。把多邊形的一個耳朵切掉,然后再對剩下的多邊形再次切割。

怎么樣的耳朵才能切呢?這個耳朵的頂點需要滿足是凸頂點且沒有其他頂點在這個耳朵里。

如何判斷是凸頂點呢?首先要知道向量外積的定義,表示向量的法向量。方向根據右手法則確定,就是手掌立在a、b所在平面的向量a上,掌心由a轉向b的過程中,大拇指的方向就是外積的方向。

對於cc.Vec2的外積就是面積,有正負之分,也是根據右手法則確定。

若多邊形ABCDEF頂點以逆時針順序排序的話,AB x BC > 0 表示B點是凸頂點。參考代碼如下。

const v1 = p2.sub(p1);
const v2 = p3.sub(p2);
if (v1.cross(v2) >= 0) {
    // 是凸點
}

判斷點D是否在三角形ABC內,可以通過外積計算點與線的位置關系判斷出。

// 判斷一個點是否在三角形內
_testInTriangle(point, triA, triB, triC) {
    let AB = triB.sub(triA), AC = triC.sub(triA), BC = triC.sub(triB), AD = point.sub(triA), BD = point.sub(triB);
    return (AB.cross(AC) >= 0 ^ AB.cross(AD) < 0)  // D,C 在AB同同方向
        && (AB.cross(AC) >= 0 ^ AC.cross(AD) >= 0) // D,B 在AC同同方向
        && (BC.cross(AB) > 0 ^ BC.cross(BD) >= 0); // D,A 在BC同同方向
},

最后把以上綜合起來就可以計算出頂點索引。

小結

以上為白玉無冰使用 Cocos Creator v2.2.2 開發"使用 mesh 實現多邊形裁剪圖片"的技術分享。有想法歡迎留言!如果這篇對你有點幫助,歡迎分享給身邊的朋友。


參考資料:
多邊形分解成三角形算法


完整代碼
原文鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM