git.iko.soy/metal-metaballs
on master help sign in
Removed (now useless) protocol.
7097ae2vinivendra
PixelImage.xcodeproj/project.pbxproj+4−8
@@ -13,13 +13,12 @@
13 2426868F1C63B72A00D62456 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2426868E1C63B72A00D62456 /* Assets.xcassets */; };
13 2426868F1C63B72A00D62456 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2426868E1C63B72A00D62456 /* Assets.xcassets */; };
14 242686921C63B72A00D62456 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 242686901C63B72A00D62456 /* LaunchScreen.storyboard */; };
14 242686921C63B72A00D62456 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 242686901C63B72A00D62456 /* LaunchScreen.storyboard */; };
15 24E1E7D71C67C8B200ECF1C4 /* UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7D61C67C8B200ECF1C4 /* UIKit.swift */; };
15 24E1E7D71C67C8B200ECF1C4 /* UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7D61C67C8B200ECF1C4 /* UIKit.swift */; };
16− 24E1E7D91C67C9C900ECF1C4 /* MetaballRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7D81C67C9C900ECF1C4 /* MetaballRenderer.swift */; };
17− 24E1E7DB1C67CA3600ECF1C4 /* ImageMetaballRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7DA1C67CA3600ECF1C4 /* ImageMetaballRenderer.swift */; };
18 24E1E7E21C67D37F00ECF1C4 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24E1E7E11C67D37F00ECF1C4 /* Metal.framework */; };
16 24E1E7E21C67D37F00ECF1C4 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24E1E7E11C67D37F00ECF1C4 /* Metal.framework */; };
19 24E1E7E41C67D39300ECF1C4 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24E1E7E31C67D39300ECF1C4 /* MetalKit.framework */; };
17 24E1E7E41C67D39300ECF1C4 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24E1E7E31C67D39300ECF1C4 /* MetalKit.framework */; };
20 24E1E7EB1C67D70300ECF1C4 /* MetalMetaballRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7EA1C67D70300ECF1C4 /* MetalMetaballRenderer.swift */; };
18 24E1E7EB1C67D70300ECF1C4 /* MetalMetaballRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7EA1C67D70300ECF1C4 /* MetalMetaballRenderer.swift */; };
21 24E1E7F01C67D74300ECF1C4 /* Metal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7EE1C67D74300ECF1C4 /* Metal.swift */; };
19 24E1E7F01C67D74300ECF1C4 /* Metal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7EE1C67D74300ECF1C4 /* Metal.swift */; };
22 24E1E7F11C67D74300ECF1C4 /* shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7EF1C67D74300ECF1C4 /* shaders.metal */; };
20 24E1E7F11C67D74300ECF1C4 /* shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 24E1E7EF1C67D74300ECF1C4 /* shaders.metal */; };
21+ 24ED21CD1C6C2397009C40FC /* MetaballDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24ED21CC1C6C2397009C40FC /* MetaballDataSource.swift */; };
23 24FFA86B1C6BA038005ACD60 /* ApproximationOperator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FFA84C1C6BA038005ACD60 /* ApproximationOperator.swift */; };
22 24FFA86B1C6BA038005ACD60 /* ApproximationOperator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FFA84C1C6BA038005ACD60 /* ApproximationOperator.swift */; };
24 24FFA86C1C6BA038005ACD60 /* Collections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FFA84D1C6BA038005ACD60 /* Collections.swift */; };
23 24FFA86C1C6BA038005ACD60 /* Collections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FFA84D1C6BA038005ACD60 /* Collections.swift */; };
25 24FFA86D1C6BA038005ACD60 /* ComparatorChains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FFA84E1C6BA038005ACD60 /* ComparatorChains.swift */; };
24 24FFA86D1C6BA038005ACD60 /* ComparatorChains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FFA84E1C6BA038005ACD60 /* ComparatorChains.swift */; };
@@ -59,13 +58,12 @@
59 242686911C63B72A00D62456 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
58 242686911C63B72A00D62456 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
60 242686931C63B72A00D62456 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
59 242686931C63B72A00D62456 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
61 24E1E7D61C67C8B200ECF1C4 /* UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKit.swift; sourceTree = "<group>"; };
60 24E1E7D61C67C8B200ECF1C4 /* UIKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKit.swift; sourceTree = "<group>"; };
62− 24E1E7D81C67C9C900ECF1C4 /* MetaballRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetaballRenderer.swift; sourceTree = "<group>"; };
63− 24E1E7DA1C67CA3600ECF1C4 /* ImageMetaballRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageMetaballRenderer.swift; sourceTree = "<group>"; };
64 24E1E7E11C67D37F00ECF1C4 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
61 24E1E7E11C67D37F00ECF1C4 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
65 24E1E7E31C67D39300ECF1C4 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
62 24E1E7E31C67D39300ECF1C4 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
66 24E1E7EA1C67D70300ECF1C4 /* MetalMetaballRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalMetaballRenderer.swift; sourceTree = "<group>"; };
63 24E1E7EA1C67D70300ECF1C4 /* MetalMetaballRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalMetaballRenderer.swift; sourceTree = "<group>"; };
67 24E1E7EE1C67D74300ECF1C4 /* Metal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Metal.swift; sourceTree = "<group>"; };
64 24E1E7EE1C67D74300ECF1C4 /* Metal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Metal.swift; sourceTree = "<group>"; };
68 24E1E7EF1C67D74300ECF1C4 /* shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = shaders.metal; sourceTree = "<group>"; };
65 24E1E7EF1C67D74300ECF1C4 /* shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = shaders.metal; sourceTree = "<group>"; };
66+ 24ED21CC1C6C2397009C40FC /* MetaballDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetaballDataSource.swift; sourceTree = "<group>"; };
69 24FFA84C1C6BA038005ACD60 /* ApproximationOperator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApproximationOperator.swift; sourceTree = "<group>"; };
67 24FFA84C1C6BA038005ACD60 /* ApproximationOperator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApproximationOperator.swift; sourceTree = "<group>"; };
70 24FFA84D1C6BA038005ACD60 /* Collections.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collections.swift; sourceTree = "<group>"; };
68 24FFA84D1C6BA038005ACD60 /* Collections.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collections.swift; sourceTree = "<group>"; };
71 24FFA84E1C6BA038005ACD60 /* ComparatorChains.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComparatorChains.swift; sourceTree = "<group>"; };
69 24FFA84E1C6BA038005ACD60 /* ComparatorChains.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComparatorChains.swift; sourceTree = "<group>"; };
@@ -134,8 +132,7 @@
134 242686871C63B72A00D62456 /* AppDelegate.swift */,
132 242686871C63B72A00D62456 /* AppDelegate.swift */,
135 242686891C63B72A00D62456 /* ViewController.swift */,
133 242686891C63B72A00D62456 /* ViewController.swift */,
136 24E1E7D61C67C8B200ECF1C4 /* UIKit.swift */,
134 24E1E7D61C67C8B200ECF1C4 /* UIKit.swift */,
137− 24E1E7D81C67C9C900ECF1C4 /* MetaballRenderer.swift */,
135+ 24ED21CC1C6C2397009C40FC /* MetaballDataSource.swift */,
138− 24E1E7DA1C67CA3600ECF1C4 /* ImageMetaballRenderer.swift */,
139 24E1E7EA1C67D70300ECF1C4 /* MetalMetaballRenderer.swift */,
136 24E1E7EA1C67D70300ECF1C4 /* MetalMetaballRenderer.swift */,
140 24E1E7EE1C67D74300ECF1C4 /* Metal.swift */,
137 24E1E7EE1C67D74300ECF1C4 /* Metal.swift */,
141 24E1E7EF1C67D74300ECF1C4 /* shaders.metal */,
138 24E1E7EF1C67D74300ECF1C4 /* shaders.metal */,
@@ -289,13 +286,13 @@
289 24FFA8861C6BA038005ACD60 /* TestCommons.swift in Sources */,
286 24FFA8861C6BA038005ACD60 /* TestCommons.swift in Sources */,
290 24FFA8741C6BA038005ACD60 /* SignOperator.swift in Sources */,
287 24FFA8741C6BA038005ACD60 /* SignOperator.swift in Sources */,
291 24FFA8821C6BA038005ACD60 /* ScanReduce.swift in Sources */,
288 24FFA8821C6BA038005ACD60 /* ScanReduce.swift in Sources */,
289+ 24ED21CD1C6C2397009C40FC /* MetaballDataSource.swift in Sources */,
292 24FFA8831C6BA038005ACD60 /* Slicing.swift in Sources */,
290 24FFA8831C6BA038005ACD60 /* Slicing.swift in Sources */,
293 24FFA8721C6BA038005ACD60 /* Sequence.swift in Sources */,
291 24FFA8721C6BA038005ACD60 /* Sequence.swift in Sources */,
294 24FFA87F1C6BA038005ACD60 /* Iterate.swift in Sources */,
292 24FFA87F1C6BA038005ACD60 /* Iterate.swift in Sources */,
295 24FFA8761C6BA038005ACD60 /* Categorise.swift in Sources */,
293 24FFA8761C6BA038005ACD60 /* Categorise.swift in Sources */,
296 24FFA86D1C6BA038005ACD60 /* ComparatorChains.swift in Sources */,
294 24FFA86D1C6BA038005ACD60 /* ComparatorChains.swift in Sources */,
297 24FFA8711C6BA038005ACD60 /* PowerOperator.swift in Sources */,
295 24FFA8711C6BA038005ACD60 /* PowerOperator.swift in Sources */,
298− 24E1E7D91C67C9C900ECF1C4 /* MetaballRenderer.swift in Sources */,
299 24E1E7D71C67C8B200ECF1C4 /* UIKit.swift in Sources */,
296 24E1E7D71C67C8B200ECF1C4 /* UIKit.swift in Sources */,
300 24FFA8851C6BA038005ACD60 /* Zip.swift in Sources */,
297 24FFA8851C6BA038005ACD60 /* Zip.swift in Sources */,
301 24FFA8791C6BA038005ACD60 /* Cycle.swift in Sources */,
298 24FFA8791C6BA038005ACD60 /* Cycle.swift in Sources */,
@@ -304,7 +301,6 @@
304 24FFA87D1C6BA038005ACD60 /* Hopping.swift in Sources */,
301 24FFA87D1C6BA038005ACD60 /* Hopping.swift in Sources */,
305 24E1E7EB1C67D70300ECF1C4 /* MetalMetaballRenderer.swift in Sources */,
302 24E1E7EB1C67D70300ECF1C4 /* MetalMetaballRenderer.swift in Sources */,
306 24FFA87A1C6BA038005ACD60 /* Enumerate.swift in Sources */,
303 24FFA87A1C6BA038005ACD60 /* Enumerate.swift in Sources */,
307− 24E1E7DB1C67CA3600ECF1C4 /* ImageMetaballRenderer.swift in Sources */,
308 242686881C63B72A00D62456 /* AppDelegate.swift in Sources */,
304 242686881C63B72A00D62456 /* AppDelegate.swift in Sources */,
309 24E1E7F01C67D74300ECF1C4 /* Metal.swift in Sources */,
305 24E1E7F01C67D74300ECF1C4 /* Metal.swift in Sources */,
310 24FFA87C1C6BA038005ACD60 /* FlatMap.swift in Sources */,
306 24FFA87C1C6BA038005ACD60 /* FlatMap.swift in Sources */,
PixelImage/ImageMetaballRenderer.swiftdeleted−115
@@ -1,115 +0,0 @@
1−
2−import UIKit
3−
4−class ImageMetaballRenderer: MetaballRenderer {
5−
6− typealias TargetView = UIImageView
7−
8− var supportsDynamicRendering: Bool { get {
9− return false
10− }
11− }
12−
13− let targetView = TargetView()
14−
15− let dataSource: MetaballDataSource
16−
17− required init(dataSource: MetaballDataSource) {
18− self.dataSource = dataSource
19− }
20−
21− func updateTargetView() {
22− let width = Int(targetView.width)
23− let height = Int(targetView.height)
24− let metaballs = dataSource.metaballs
25−
26− let bytesPerPixel = 4;
27− let bytesPerRow = bytesPerPixel * width;
28− let bitsPerComponent = 8;
29−
30− var matrix = PixelMatrix(width: width, height: height)
31− for i in 0..<width {
32− for j in 0..<height {
33− let pixelPosition = CGPoint(x: i, y: j)
34−
35− var sum: CGFloat = 0
36−
37− for combo in metaballs.combos() {
38− let metaball1 = combo[0].middle
39− let metaball2 = combo[1].middle
40−
41− let metaball1Vector = metaball1 - pixelPosition
42− let metaball2Vector = metaball2 - pixelPosition
43−
44− let direction1 = metaball1Vector.normalized
45− let direction2 = metaball2Vector.normalized
46−
47− let cos = direction1 * direction2
48−
49− let value1 = 255000 / (metaball1Vector * metaball1Vector + 1)
50− let value2 = 255000 / (metaball2Vector * metaball2Vector + 1)
51−
52− let v = gradient(value1 + value2)
53− let link = ((1 - cos) * 0.5) ^ 50
54−
55− let weightedLink = 128 * CGFloat(link)
56− let weightedValue = 0.6 * CGFloat(v)
57−
58− sum += weightedValue + weightedLink
59− }
60−
61− let result = threshold(sum)
62−
63− matrix.set(x: i, y: j, r:0, g:result/2, b:result)
64− }
65− }
66−
67− let buffer: UnsafeMutablePointer<Void> = UnsafeMutablePointer(matrix.pixels)
68−
69− let colorSpace = CGColorSpaceCreateDeviceRGB()
70− let context = CGBitmapContextCreate(buffer, width, height, bitsPerComponent, bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedLast.rawValue | CGBitmapInfo.ByteOrder32Big.rawValue);
71−
72− let cgImage = CGBitmapContextCreateImage(context)
73− let image = UIImage(CGImage: cgImage!)
74− targetView.image = image
75− }
76−}
77−
78−struct PixelMatrix {
79− var pixels: [UInt8]
80−
81− let width: Int
82− let height: Int
83−
84− init(width: Int, height: Int) {
85− self.width = width
86− self.height = height
87− pixels = [UInt8](count: (4 * width * height), repeatedValue: 255)
88− }
89−
90− mutating func set(x x: Int, y: Int, r: UInt8, g: UInt8, b: UInt8) {
91− let index = 4 * (y * width + x)
92− pixels[index ] = r
93− pixels[index + 1] = g
94− pixels[index + 2] = b
95− }
96−
97− mutating func set(x x: Int, y: Int, white: UInt8) {
98− let index = 4 * (y * width + x)
99− pixels[index ] = white
100− pixels[index + 1] = white
101− pixels[index + 2] = white
102− }
103−}
104−
105−func threshold(value: CGFloat) -> UInt8 {
106− return value < 128 ? 0 : 255
107−}
108−
109−func gradient(value: CGFloat) -> UInt8 {
110− return UInt8(min(max(value, 0), CGFloat(255)))
111−}
112−
113−func thresholdf(value value: CGFloat, cap: CGFloat = 0.5) -> CGFloat {
114− return value < cap ? 0 : 1.0
115−}
PixelImage/MetaballDataSource.swiftnew file+6
@@ -0,0 +1,6 @@
1+
2+import Metal
3+
4+protocol MetaballDataSource {
5+ var metaballs: [Metaball] { get }
6+}
PixelImage/MetaballRenderer.swiftdeleted−17
@@ -1,17 +0,0 @@
1−
2−import UIKit
3−
4−protocol MetaballDataSource {
5− var metaballs: [Metaball] { get }
6−}
7−
8−protocol MetaballRenderer {
9− typealias TargetView: UIView
10−
11− var targetView: TargetView { get }
12− var supportsDynamicRendering: Bool { get }
13−
14− init(dataSource: MetaballDataSource)
15−
16− func updateTargetView()
17−}
PixelImage/ViewController.swift+3−6
@@ -3,11 +3,8 @@ import UIKit
3
3
4class ViewController: UIViewController, MetaballDataSource {
4class ViewController: UIViewController, MetaballDataSource {
5
5
6− typealias Renderer = MetalMetaballRenderer // ImageMetaballRenderer // MetalMetaballRenderer
7− typealias TargetView = Renderer.TargetView
8−
9− var metaballView: TargetView!
6+ var metaballView: UIImageView!
10− var renderer: Renderer!
7+ var renderer: MetalMetaballRenderer!
11
8
12 let width = 350
9 let width = 350
13 let height = 600
10 let height = 600
@@ -25,7 +22,7 @@ class ViewController: UIViewController, MetaballDataSource {
25
22
26 let border = 20
23 let border = 20
27 let metaballViewFrame = CGRect(x: border/2, y: border/2, width: width, height: height)
24 let metaballViewFrame = CGRect(x: border/2, y: border/2, width: width, height: height)
28− renderer = Renderer(dataSource: self, frame: metaballViewFrame)
25+ renderer = MetalMetaballRenderer(dataSource: self, frame: metaballViewFrame)
29 metaballView = renderer.targetView
26 metaballView = renderer.targetView
30
27
31 let bigView = UIView(frame: CGRect(x: 10, y: 70, width: width + border, height: height + border))
28 let bigView = UIView(frame: CGRect(x: 10, y: 70, width: width + border, height: height + border))