git.iko.soy/metal-metaballs
on master help sign in
Added state machine and internal loop.
commitaee469b7a7f6789a2ab37ad71b9d9de97baec0d0 authorvinivendra <vinivendra@gmail.com> dateWed 10 Feb 2016, 20:35 (11 years ago) parentc7661fc
2 files changed+37−18
PixelImage/MetalMetaballRenderer.swift+35−9 PixelImage/ViewController.swift+2−9
PixelImage/MetalMetaballRenderer.swift+35−9
@@ -1,5 +1,3 @@
1−// TODO: Create state machine
2−// TODO: Make draw calls auto-loop, conditioned to the state machine
31// TODO: Create compute context to contain texture and imageBuffer
42// TOOD: Use two compute contexts and double recursion
53
@@ -12,6 +10,8 @@
1210import Metal
1311import UIKit
1412
13+var i = 0
14+
1515class MetalMetaballRenderer: MetaballRenderer {
1616
1717 typealias TargetView = UIImageView
@@ -33,12 +33,32 @@ class MetalMetaballRenderer: MetaballRenderer {
3333 var dirty = false
3434 var metalIsBusy = false
3535
36+ enum RendererState {
37+ case Idle
38+ case Running
39+ case Ending
40+ }
41+
42+ var state: RendererState = .Idle {
43+ willSet {
44+ if state == .Idle {
45+ if newValue == .Running {
46+ updateTargetView()
47+ }
48+ }
49+ }
50+ }
51+
3652 required init(dataSource: MetaballDataSource) {
3753 self.dataSource = dataSource
3854 }
3955
4056 func updateTargetView() {
4157
58+ print("Update \(i++)!")
59+
60+ state = .Ending
61+
4262 // Re-alloc buffers if the size has changed
4363 if previousSize != targetView.size {
4464 previousSize = targetView.size
@@ -56,6 +76,12 @@ class MetalMetaballRenderer: MetaballRenderer {
5676 dispatch_async(dispatch_get_main_queue(), { () -> Void in
5777 // Send image to view
5878 self.targetView.image = uiimage
79+
80+ if self.state != .Running {
81+ self.state = .Idle
82+ } else {
83+ self.updateTargetView()
84+ }
5985 })
6086 }
6187 }
@@ -97,7 +123,7 @@ class MetalMetaballRenderer: MetaballRenderer {
97123
98124 commandBuffer.commit()
99125 commandBuffer.waitUntilCompleted()
100−
126+
101127 } catch _ {
102128 print("Error!")
103129 }
@@ -155,9 +181,9 @@ class MetalMetaballRenderer: MetaballRenderer {
155181 let x = CGFloat(metaball.midX)
156182 let y = CGFloat(metaball.midY)
157183 if -border < x ≤ targetView.width + border &&
158− -border < y ≤ targetView.height + border {
159− array.append(Float(x))
160− array.append(Float(y))
184+ -border < y ≤ targetView.height + border {
185+ array.append(Float(x))
186+ array.append(Float(y))
161187 }
162188 return array
163189 }
@@ -166,17 +192,17 @@ class MetalMetaballRenderer: MetaballRenderer {
166192
167193 // Create buffer
168194 let buffer = context.device.newBufferWithBytes(floats, length: floats.count * sizeof(Float), options: .StorageModeShared)
169−
195+
170196 return buffer
171197 }
172−
198+
173199 func updateFrame() {
174200 if imageBuffer != nil {
175201 free(imageBuffer)
176202 }
177203 imageBuffer = nil
178204 }
179−
205+
180206 deinit {
181207 free(imageBuffer)
182208 }
PixelImage/ViewController.swift+2−9
@@ -36,13 +36,11 @@ class ViewController: UIViewController, MetaballDataSource {
3636 bigView.addSubview(metaballView)
3737 view.addSubview(bigView)
3838
39−
4039 for metaball in metaballs {
4140 metaballView.addSubview(metaball)
4241 }
4342
44−
45− renderer.updateTargetView()
43+ renderer.state = .Running
4644 }
4745
4846 func handlePan(recognizer: UIPanGestureRecognizer) {
@@ -58,12 +56,7 @@ class ViewController: UIViewController, MetaballDataSource {
5856
5957 selectedMetaball?.middle = location
6058
61− if recognizer.state == .Changed && renderer.supportsDynamicRendering {
62− renderer.updateTargetView()
63− }
64− if recognizer.state == .Ended {
65− renderer.updateTargetView()
66− }
59+ renderer.state = .Running
6760 }
6861}
6962