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世界中,物体相对位置不对,直接没有做到碰撞检测。

原文地址:https://www.cnblogs.com/zhong-dev/p/11215294.html