@@ -1,5 +1,3 @@
1−// TODO: Create state machine
2−// TODO: Make draw calls auto-loop, conditioned to the state machine
3// TODO: Create compute context to contain texture and imageBuffer
1// TODO: Create compute context to contain texture and imageBuffer
4// TOOD: Use two compute contexts and double recursion
2// TOOD: Use two compute contexts and double recursion
@@ -12,6 +10,8 @@
12import Metal
10import Metal
13import UIKit
11import UIKit
15class MetalMetaballRenderer: MetaballRenderer {
15class MetalMetaballRenderer: MetaballRenderer {
17 typealias TargetView = UIImageView
17 typealias TargetView = UIImageView
@@ -33,12 +33,32 @@ class MetalMetaballRenderer: MetaballRenderer {
33 var dirty = false
33 var dirty = false
34 var metalIsBusy = false
34 var metalIsBusy = false
42+ var state: RendererState = .Idle {
45+ if newValue == .Running {
36 required init(dataSource: MetaballDataSource) {
52 required init(dataSource: MetaballDataSource) {
37 self.dataSource = dataSource
53 self.dataSource = dataSource
40 func updateTargetView() {
56 func updateTargetView() {
58+ print("Update \(i++)!")
42 // Re-alloc buffers if the size has changed
62 // Re-alloc buffers if the size has changed
43 if previousSize != targetView.size {
63 if previousSize != targetView.size {
44 previousSize = targetView.size
64 previousSize = targetView.size
@@ -56,6 +76,12 @@ class MetalMetaballRenderer: MetaballRenderer {
56 dispatch_async(dispatch_get_main_queue(), { () -> Void in
76 dispatch_async(dispatch_get_main_queue(), { () -> Void in
57 // Send image to view
77 // Send image to view
58 self.targetView.image = uiimage
78 self.targetView.image = uiimage
80+ if self.state != .Running {
83+ self.updateTargetView()
@@ -97,7 +123,7 @@ class MetalMetaballRenderer: MetaballRenderer {
98 commandBuffer.commit()
124 commandBuffer.commit()
99 commandBuffer.waitUntilCompleted()
125 commandBuffer.waitUntilCompleted()
101 } catch _ {
127 } catch _ {
102 print("Error!")
128 print("Error!")
@@ -155,9 +181,9 @@ class MetalMetaballRenderer: MetaballRenderer {
155 let x = CGFloat(metaball.midX)
181 let x = CGFloat(metaball.midX)
156 let y = CGFloat(metaball.midY)
182 let y = CGFloat(metaball.midY)
157 if -border < x ≤ targetView.width + border &&
183 if -border < x ≤ targetView.width + border &&
158− -border < y ≤ targetView.height + border {
184+ -border < y ≤ targetView.height + border {
159− array.append(Float(x))
185+ array.append(Float(x))
160− array.append(Float(y))
186+ array.append(Float(y))
162 return array
188 return array
@@ -166,17 +192,17 @@ class MetalMetaballRenderer: MetaballRenderer {
167 // Create buffer
193 // Create buffer
168 let buffer = context.device.newBufferWithBytes(floats, length: floats.count * sizeof(Float), options: .StorageModeShared)
194 let buffer = context.device.newBufferWithBytes(floats, length: floats.count * sizeof(Float), options: .StorageModeShared)
170 return buffer
196 return buffer
173 func updateFrame() {
199 func updateFrame() {
174 if imageBuffer != nil {
200 if imageBuffer != nil {
175 free(imageBuffer)
201 free(imageBuffer)
177 imageBuffer = nil
203 imageBuffer = nil
181 free(imageBuffer)
207 free(imageBuffer)