这是在上一篇文章画扇形的基础上实现的,基本上还是来源于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世界中,物体相对位置不对,直接没有做到碰撞检测。