S04E03:圆形平面网格生成

591 阅读2分钟

说明

有时我们需要圆形的平面网格,并且需要控制贴图的形状,本文讲述如何生成一个圆形的平面。

几何

其实简单地说,圆形网格就是将方形网格进行变形而已:将原来按 x, y 方向水平竖直的网格,变成了沿径向(半径方向 0~R)、切向(环向角度 0~360)排列而已。 这样一来,贴图的方向也有了两种选择:

  • 将贴图 UV 方向也按径向、切向扭曲排列。如下图左侧;
  • 将贴图 UV 按实际坐标位置线性排列。如下图右侧;

代码

public static func generateCirclePlane(radius: Float, angularResolution: Int, radialResolution: Int, circleUV: Bool = true) throws -> MeshResource {
    var descr = MeshDescriptor()
    var meshPositions: [SIMD3<Float>] = []
    var indices: [UInt32] = []
    var textureMap: [SIMD2<Float>] = []
    
    let radial = radialResolution > 0 ? radialResolution : 1
    let angular = angularResolution > 2 ? angularResolution : 3;

    let radialf = Float(radial)
    let angularf = Float(angular)
    
    let radialInc = radius / radialf
    let angularInc = (2.0 * Float.pi) / angularf

    let perLoop = angular + 1

    for r in 0...radial {
        let rf = Float(r)
        let rad = rf * radialInc
        let rFactor = rf / radialf
        for a in 0...angular {
            let af = Float(a)
            let angle = af * angularInc
            let ca = cos(angle)
            let sa = sin(angle)

            meshPositions.append(SIMD3<Float>(rad * ca, 0, rad * sa))
            if circleUV {
                textureMap.append(SIMD2<Float>(rFactor, 1 - af / angularf))
            } else {
                textureMap.append(SIMD2<Float>((ca*rFactor)/2+0.5, 0.5-(sa*rFactor)/2))
            }
            
            if (r != radial && a != angular) {
                let index = UInt32(a + r * perLoop)

                let tl = index
                let tr = tl + 1
                let bl = index + UInt32(perLoop)
                let br = bl + 1

                indices.append(contentsOf: [tr,bl,tl,
                                            br,bl,tr])
            }
        }
    }
    
    descr.primitives = .triangles(indices)
    descr.positions = MeshBuffer(meshPositions)
    descr.textureCoordinates = MeshBuffers.TextureCoordinates(textureMap)
    return try .generate(from: [descr])
}

补充

可能会有人注意到,在圆形的中心,会有很多个点重叠在一起。那么这些重叠的点,能不能合并成一个点呢?

其实判断能不能合并的规则很简单:除了位置相同,它们的法线和 UV 是否也相同,如果都相同则可以合并,只要有一个不同就不适合合并。

如果使用默认的环形贴图模式,显示 UV 坐标并不相同,所以无法简单合并。