diff --git a/MetaballsKit/MarchingSquares.swift b/MetaballsKit/MarchingSquares.swift index 54e6db6..ce174ef 100644 --- a/MetaballsKit/MarchingSquares.swift +++ b/MetaballsKit/MarchingSquares.swift @@ -26,12 +26,15 @@ class MarchingSquares { func setupMetal(withDevice device: MTLDevice) { let xSamples = Int(field.size.x / sampleGridSize.x) let ySamples = Int(field.size.y / sampleGridSize.y) + guard xSamples > 1 && ySamples > 1 else { + return + } let samplesDesc = MTLTextureDescriptor() samplesDesc.textureType = .type2D samplesDesc.width = xSamples samplesDesc.height = ySamples - samplesDesc.pixelFormat = .depth32Float + samplesDesc.pixelFormat = .r32Float samples = device.makeTexture(descriptor: samplesDesc) let indexesDesc = MTLTextureDescriptor() @@ -61,4 +64,44 @@ class MarchingSquares { } } } + + func populateIndexes() { + guard let indexes = indexes else { return } + + let bytesPerRow = indexes.width * MemoryLayout.stride + + for x in 0.. 1.0 ? 0b1000 : 0) + + (samples[1] > 1.0 ? 0b0100 : 0) + + (samples[2] > 1.0 ? 0b0001 : 0) + + (samples[3] > 1.0 ? 0b0010 : 0) + + let origin = MTLOrigin(x: x, y: y, z: 0) + let size = MTLSize(width: 1, height: 1, depth: 1) + let region = MTLRegion(origin: origin, size: size) + let indexArr = [index] + indexes.replace(region: region, mipmapLevel: 0, withBytes: indexArr, bytesPerRow: bytesPerRow) + } + } + } + + private func getSampleBlock(x: Int, y: Int) -> [Float]? { + guard let samples = samples else { + return nil + } + + var block: [Float] = [0, 0, 0, 0] + let bytesPerRow = samples.width * MemoryLayout.stride + let origin = MTLOrigin(x: x, y: y, z: 0) + let size = MTLSize(width: 2, height: 2, depth: 1) + let region = MTLRegion(origin: origin, size: size) + samples.getBytes(&block, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0) + + return block + } } diff --git a/MetaballsKit/Metaballs.swift b/MetaballsKit/Metaballs.swift index fa1e1a3..d4966e2 100644 --- a/MetaballsKit/Metaballs.swift +++ b/MetaballsKit/Metaballs.swift @@ -119,6 +119,9 @@ public class Field { public var defaults = UserDefaults.standard private var parameters: Parameters + private lazy var marchingSquares: MarchingSquares = { + return MarchingSquares(field: self) + }() internal var bounds: CGRect { return CGRect(origin: CGPoint(), size: CGSize(size: size)) @@ -155,7 +158,10 @@ public class Field { } } } + populateBallBuffer() + marchingSquares.sampleField() + marchingSquares.populateIndexes() } func add(ballWithRadius radius: Float) { @@ -264,6 +270,7 @@ public class Field { self.device = device populateParametersBuffer() populateBallBuffer() + marchingSquares.setupMetal(withDevice: device) } // MARK: - Notifications