LayaAir2.0 自定義Mesh-畫圓環


  這是在上一篇文章畫扇形的基礎上實現的,基本上還是來源於Laya官方提供的畫圓柱的Mesh代碼實現。

  圓環相較於扇形或者圓柱,是增加了內徑,要切除掉一部分中間區域。最終的表現為上下部分的圓環,內部、外部的封邊。在畫扇形、圓柱的基礎上,需要改一下上下圓環,然后增加一個內部的封邊。

  一開始覺得畫上下的圓環很簡單,就是圓環半徑,減去圓環內徑,然后把剩下的區域畫出來就行,但是代碼該咋寫呢。。。后來想一下,圓柱體外部封邊也可以看成畫了一個環,那是不是就可以直接基於那部分代碼來修改呢?

// 畫出上圓環
for (let bv = 0; bv <= slices; bv++) {
    curAngle = bv * sliceAngle

    posY = halfHeight

    vertices[vc++] = Math.cos(curAngle) * innerRadius vertices[vc + (slices + 1) * 8 - 1] = Math.cos(curAngle) * radius

    vertices[vc++] = posY
    vertices[vc + (slices + 1) * 8 - 1] = posY

    vertices[vc++] = Math.sin(curAngle) * innerRadius vertices[vc + (slices + 1) * 8 - 1] = Math.sin(curAngle) * radius

    vertices[vc++] = 0
    vertices[vc + (slices + 1) * 8 - 1] = 0

    vertices[vc++] = 1
    vertices[vc + (slices + 1) * 8 - 1] = 1

    vertices[vc++] = 0
    vertices[vc + (slices + 1) * 8 - 1] = 0

    vertices[vc++] = 1 - bv * 1 / slices
    vertices[vc + (slices + 1) * 8 - 1] = 1 - bv * 1 / slices

    vertices[vc++] = 0
    vertices[vc + (slices + 1) * 8 - 1] = 1
}
vc += (slices + 1) * 8
// 上環顯示的是正面,所以頂點索引要順序
for (let ri = 0; ri < slices; ri++) {
    indices[ic++] = ri + verticeCount + (slices + 1)
    indices[ic++] = ri + verticeCount + 1
    indices[ic++] = ri + verticeCount
    indices[ic++] = ri + verticeCount + (slices + 1)
    indices[ic++] = ri + verticeCount + (slices + 1) + 1
    indices[ic++] = ri + verticeCount + 1
}
verticeCount += 2 * (slices + 1)

  上述代碼就是在畫圓柱外部封邊的基礎上修改而來的,紅色標記的就是修改的地方,把坐標改成內外徑而已。

  內部封邊,則基本上可以照着外封邊的代碼來改:

// 畫出厚度內圈
    for (let rv = 0; rv <= slices; rv++) {
        curAngle = rv * sliceAngle
        posX = Math.cos(curAngle) * innerRadius posY = halfHeight posZ = Math.sin(curAngle) * innerRadius

        vertices[vc++] = posX
        vertices[vc + (slices + 1) * 8 - 1] = posX

        vertices[vc++] = posY
        vertices[vc + (slices + 1) * 8 - 1] = -posY

        vertices[vc++] = posZ
        vertices[vc + (slices + 1) * 8 - 1] = posZ

        vertices[vc++] = posX
        vertices[vc + (slices + 1) * 8 - 1] = posX

        vertices[vc++] = 0
        vertices[vc + (slices + 1) * 8 - 1] = 0

        vertices[vc++] = posZ
        vertices[vc + (slices + 1) * 8 - 1] = posZ

        // 內圈顯示的是背面,這里將數值調一下,顯示背面
        vertices[vc++] = rv * 1 / slices - 1 vertices[vc + (slices + 1) * 8 - 1] = rv * 1 / slices - 1

        vertices[vc++] = 0
        vertices[vc + (slices + 1) * 8 - 1] = 1
    }
    vc += (slices + 1) * 8
    // z軸三角 顯示背面,逆序
    for (let ri = 0; ri < slices; ri++) {
        indices[ic++] = ri + verticeCount + (slices + 1)
        indices[ic++] = ri + verticeCount
        indices[ic++] = ri + verticeCount + 1
        indices[ic++] = ri + verticeCount + (slices + 1)
        indices[ic++] = ri + verticeCount + 1
        indices[ic++] = ri + verticeCount + (slices + 1) + 1
    }
    verticeCount += 2 * (slices + 1)

  改動的地方基本上就是坐標值用的是內徑的長度。然后有兩個地方要注意,首先是索引順序,因為內徑在表現上來說是看到了3D物體的背面,所以頂點索引是逆序的;再者是8個數據中倒數第二位UV坐標X值,這個是我猜着改的,改動之后,內部封邊的貼圖顯示就正常了。

  如果要畫半環,那還是跟畫扇形一樣,改一下頂點數,就能畫出正常的3D環形了。

  自定義Mesh畫出來的模型,也是可以添加物理碰撞器和剛體的,只是碰撞形狀的數據,要用模型的數據,例如:

let ring = createRing(...)
// 碰撞器
let ringCollider = ring.addComponent(Laya.PhysicsCollider)
let ringShape = new Laya.MeshColliderShape()
ringShape.mesh = ring.meshFilter.sharedMesh
ringCollider.colliderShape = ringShape

  之前在這個地方卡了很久,一直不生效,后來再改動改動坐標,發現是在3D世界中,物體相對位置不對,直接沒有做到碰撞檢測。


免責聲明!

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



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