Use the simd types where I can
This commit is contained in:
parent
edce32e021
commit
8f1e1335bd
9 changed files with 107 additions and 144 deletions
|
|
@ -29,6 +29,8 @@
|
||||||
C0FF7C992168062C0081B781 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = C0BBE3A91F2E91D900E68524 /* Shaders.metal */; };
|
C0FF7C992168062C0081B781 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = C0BBE3A91F2E91D900E68524 /* Shaders.metal */; };
|
||||||
C0FF7C9A2168062C0081B781 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0B906D41F45432700B5F89B /* Preferences.swift */; };
|
C0FF7C9A2168062C0081B781 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0B906D41F45432700B5F89B /* Preferences.swift */; };
|
||||||
C0FF7C9B2168062C0081B781 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C091616F1F3F5AE6009C4263 /* PreferencesViewController.swift */; };
|
C0FF7C9B2168062C0081B781 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C091616F1F3F5AE6009C4263 /* PreferencesViewController.swift */; };
|
||||||
|
C0FF7C9D216A6DE00081B781 /* Math.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FF7C9C216A6DE00081B781 /* Math.swift */; };
|
||||||
|
C0FF7C9E216A6DE00081B781 /* Math.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0FF7C9C216A6DE00081B781 /* Math.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
|
@ -78,6 +80,7 @@
|
||||||
C0BBE3AB1F2E941200E68524 /* Renderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Renderer.swift; sourceTree = "<group>"; };
|
C0BBE3AB1F2E941200E68524 /* Renderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Renderer.swift; sourceTree = "<group>"; };
|
||||||
C0CE7BFF1F362C3F001516B6 /* Geometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = "<group>"; };
|
C0CE7BFF1F362C3F001516B6 /* Geometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = "<group>"; };
|
||||||
C0DF1D781F3789DC0038B0A0 /* Memory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memory.swift; sourceTree = "<group>"; };
|
C0DF1D781F3789DC0038B0A0 /* Memory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memory.swift; sourceTree = "<group>"; };
|
||||||
|
C0FF7C9C216A6DE00081B781 /* Math.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Math.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -167,6 +170,7 @@
|
||||||
C0BBE3A31F2E81C700E68524 /* Metaballs.swift */,
|
C0BBE3A31F2E81C700E68524 /* Metaballs.swift */,
|
||||||
C0CE7BFF1F362C3F001516B6 /* Geometry.swift */,
|
C0CE7BFF1F362C3F001516B6 /* Geometry.swift */,
|
||||||
C0DF1D781F3789DC0038B0A0 /* Memory.swift */,
|
C0DF1D781F3789DC0038B0A0 /* Memory.swift */,
|
||||||
|
C0FF7C9C216A6DE00081B781 /* Math.swift */,
|
||||||
C0BBE3AB1F2E941200E68524 /* Renderer.swift */,
|
C0BBE3AB1F2E941200E68524 /* Renderer.swift */,
|
||||||
C0BBE3A91F2E91D900E68524 /* Shaders.metal */,
|
C0BBE3A91F2E91D900E68524 /* Shaders.metal */,
|
||||||
C0B906D41F45432700B5F89B /* Preferences.swift */,
|
C0B906D41F45432700B5F89B /* Preferences.swift */,
|
||||||
|
|
@ -345,6 +349,7 @@
|
||||||
files = (
|
files = (
|
||||||
C0FF7C992168062C0081B781 /* Shaders.metal in Sources */,
|
C0FF7C992168062C0081B781 /* Shaders.metal in Sources */,
|
||||||
C0FF7C9A2168062C0081B781 /* Preferences.swift in Sources */,
|
C0FF7C9A2168062C0081B781 /* Preferences.swift in Sources */,
|
||||||
|
C0FF7C9E216A6DE00081B781 /* Math.swift in Sources */,
|
||||||
C0FF7C972168062C0081B781 /* Memory.swift in Sources */,
|
C0FF7C972168062C0081B781 /* Memory.swift in Sources */,
|
||||||
C0FF7C9B2168062C0081B781 /* PreferencesViewController.swift in Sources */,
|
C0FF7C9B2168062C0081B781 /* PreferencesViewController.swift in Sources */,
|
||||||
C0B906E91F455D1A00B5F89B /* MetaballsSaverView.swift in Sources */,
|
C0B906E91F455D1A00B5F89B /* MetaballsSaverView.swift in Sources */,
|
||||||
|
|
@ -367,6 +372,7 @@
|
||||||
C0FF7C912168062B0081B781 /* Renderer.swift in Sources */,
|
C0FF7C912168062B0081B781 /* Renderer.swift in Sources */,
|
||||||
C0FF7C932168062B0081B781 /* Preferences.swift in Sources */,
|
C0FF7C932168062B0081B781 /* Preferences.swift in Sources */,
|
||||||
C0BBE36B1F2E816500E68524 /* AppDelegate.swift in Sources */,
|
C0BBE36B1F2E816500E68524 /* AppDelegate.swift in Sources */,
|
||||||
|
C0FF7C9D216A6DE00081B781 /* Math.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,91 +7,18 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import simd
|
||||||
|
|
||||||
public struct Point {
|
public typealias Size = packed_uint2
|
||||||
var x: Float
|
|
||||||
var y: Float
|
|
||||||
|
|
||||||
var CGPoint: CGPoint {
|
|
||||||
return CoreGraphics.CGPoint(x: CGFloat(x), y: CGFloat(y))
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
self.init(x: 0, y: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(x: Float, y: Float) {
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Point: CustomStringConvertible {
|
|
||||||
public var description: String {
|
|
||||||
return "(\(x), \(y))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Size {
|
|
||||||
var width: UInt16
|
|
||||||
var height: UInt16
|
|
||||||
|
|
||||||
public init() {
|
|
||||||
self.init(width: 0, height: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(width: UInt16, height: UInt16) {
|
|
||||||
self.width = width
|
|
||||||
self.height = height
|
|
||||||
}
|
|
||||||
|
|
||||||
|
extension Size {
|
||||||
public init(size: CGSize) {
|
public init(size: CGSize) {
|
||||||
self.init(width: UInt16(size.width), height: UInt16(size.height))
|
self.init(UInt32(size.width), UInt32(size.height))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Size: CustomStringConvertible {
|
extension Size: CustomStringConvertible {
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return "(\(width), \(height))"
|
return "(\(x), \(y))"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Size: Equatable {
|
|
||||||
/// Returns a Boolean value indicating whether two values are equal.
|
|
||||||
///
|
|
||||||
/// Equality is the inverse of inequality. For any values `a` and `b`,
|
|
||||||
/// `a == b` implies that `a != b` is `false`.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - lhs: A value to compare.
|
|
||||||
/// - rhs: Another value to compare.
|
|
||||||
public static func ==(lhs: Size, rhs: Size) -> Bool {
|
|
||||||
return lhs.width == rhs.width && lhs.height == rhs.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension CGSize {
|
|
||||||
init(size: Size) {
|
|
||||||
self.init(width: CGFloat(size.width), height: CGFloat(size.height))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Vector {
|
|
||||||
var dx: Float
|
|
||||||
var dy: Float
|
|
||||||
|
|
||||||
init() {
|
|
||||||
self.init(dx: 0, dy: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(dx: Float, dy: Float) {
|
|
||||||
self.dx = dx
|
|
||||||
self.dy = dy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Vector: CustomStringConvertible {
|
|
||||||
public var description: String {
|
|
||||||
return "(\(dx), \(dy))"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
63
MetaballsKit/Math.swift
Normal file
63
MetaballsKit/Math.swift
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
//
|
||||||
|
// Math.swift
|
||||||
|
// Metaballs
|
||||||
|
//
|
||||||
|
// Created by Eryn Wells on 9/22/18.
|
||||||
|
// Copyright © 2018 Eryn Wells. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
import Foundation
|
||||||
|
import simd
|
||||||
|
|
||||||
|
public typealias Float2 = packed_float2
|
||||||
|
public typealias Float3 = float3
|
||||||
|
public typealias Float4 = float4
|
||||||
|
public typealias Matrix3x3 = float3x3
|
||||||
|
public typealias Matrix4x4 = float4x4
|
||||||
|
|
||||||
|
extension Float2 {
|
||||||
|
var CGPoint: CGPoint {
|
||||||
|
return CoreGraphics.CGPoint(x: CGFloat(x), y: CGFloat(y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Float2: CustomStringConvertible {
|
||||||
|
public var description: String {
|
||||||
|
return "(\(x), \(y))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Float4 {
|
||||||
|
public init(r: Float, g: Float, b: Float, a: Float) {
|
||||||
|
self.init(r, g, b, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(color: NSColor) {
|
||||||
|
if let convertedColor = color.usingColorSpace(NSColorSpace.deviceRGB) {
|
||||||
|
self.init(Float(convertedColor.redComponent), Float(convertedColor.greenComponent), Float(convertedColor.blueComponent), Float(convertedColor.alphaComponent))
|
||||||
|
} else {
|
||||||
|
self.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Matrix4x4 {
|
||||||
|
/// Create a 4x4 orthographic projection matrix with the provided 6-tuple.
|
||||||
|
/// @see https://en.wikipedia.org/wiki/Orthographic_projection
|
||||||
|
static func orthographicProjection(top: Float32, left: Float32, bottom: Float32, right: Float32, near: Float32, far: Float32) -> Matrix4x4 {
|
||||||
|
let rows = [
|
||||||
|
Float4(2.0 / (right - left), 0.0, 0.0, -(right + left) / (right - left)),
|
||||||
|
Float4(0.0, 2.0 / (top - bottom), 0.0, -(top + bottom) / (top - bottom)),
|
||||||
|
Float4(0.0, 0.0, -2.0 / (far - near), -(far + near) / (far - near)),
|
||||||
|
Float4(0.0, 0.0, 0.0, 1.0)
|
||||||
|
]
|
||||||
|
return Matrix4x4(rows)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CGSize {
|
||||||
|
init(size: Size) {
|
||||||
|
self.init(width: CGFloat(size.x), height: CGFloat(size.y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import simd
|
||||||
|
|
||||||
extension UnsafeMutableRawPointer {
|
extension UnsafeMutableRawPointer {
|
||||||
func writeAndAdvance<T>(value: inout T) -> UnsafeMutableRawPointer {
|
func writeAndAdvance<T>(value: inout T) -> UnsafeMutableRawPointer {
|
||||||
|
|
@ -17,38 +18,6 @@ extension UnsafeMutableRawPointer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metal's float4 type. 4 bytes per float, 16 bytes total, 16 byte aligned.
|
|
||||||
public struct Float4 {
|
|
||||||
public var x: Float = 0
|
|
||||||
public var y: Float = 0
|
|
||||||
public var z: Float = 0
|
|
||||||
public var w: Float = 0
|
|
||||||
|
|
||||||
public init() { }
|
|
||||||
|
|
||||||
public init(_ x: Float, _ y: Float, _ z: Float, _ w: Float) {
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.z = z
|
|
||||||
self.w = w
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(r: Float, g: Float, b: Float, a: Float) {
|
|
||||||
x = r
|
|
||||||
y = g
|
|
||||||
z = b
|
|
||||||
w = a
|
|
||||||
}
|
|
||||||
|
|
||||||
init(color: NSColor) {
|
|
||||||
if let convertedColor = color.usingColorSpace(NSColorSpace.deviceRGB) {
|
|
||||||
self.init(Float(convertedColor.redComponent), Float(convertedColor.greenComponent), Float(convertedColor.blueComponent), Float(convertedColor.alphaComponent))
|
|
||||||
} else {
|
|
||||||
self.init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension NSColor {
|
extension NSColor {
|
||||||
convenience init(float4: Float4) {
|
convenience init(float4: Float4) {
|
||||||
self.init(deviceRed: CGFloat(float4.x), green: CGFloat(float4.y), blue: CGFloat(float4.z), alpha: CGFloat(float4.w))
|
self.init(deviceRed: CGFloat(float4.x), green: CGFloat(float4.y), blue: CGFloat(float4.z), alpha: CGFloat(float4.w))
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ public enum MetaballsError: Error {
|
||||||
case metalError(String)
|
case metalError(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ColorStyle: UInt16 {
|
public enum ColorStyle: UInt32 {
|
||||||
/// Single flat color
|
/// Single flat color
|
||||||
case singleColor = 1
|
case singleColor = 1
|
||||||
/// Two color horizontal gradient
|
/// Two color horizontal gradient
|
||||||
|
|
@ -33,8 +33,8 @@ public struct Parameters {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulation parameters
|
// Simulation parameters
|
||||||
var size = Size(width: 0, height: 0)
|
var size = Size(0, 0)
|
||||||
var numberOfBalls: UInt16 = 0
|
var numberOfBalls: UInt32 = 0
|
||||||
|
|
||||||
private var _colorStyle = ColorStyle.singleColor.rawValue
|
private var _colorStyle = ColorStyle.singleColor.rawValue
|
||||||
|
|
||||||
|
|
@ -69,8 +69,8 @@ public struct Parameters {
|
||||||
|
|
||||||
public struct Ball {
|
public struct Ball {
|
||||||
let radius: Float
|
let radius: Float
|
||||||
var position = Point()
|
var position = Float2()
|
||||||
var velocity = Vector()
|
var velocity = Float2()
|
||||||
|
|
||||||
internal var bounds: CGRect {
|
internal var bounds: CGRect {
|
||||||
let diameter = CGFloat(radius * 2)
|
let diameter = CGFloat(radius * 2)
|
||||||
|
|
@ -78,8 +78,8 @@ public struct Ball {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal mutating func update() {
|
internal mutating func update() {
|
||||||
position.x += velocity.dx
|
position.x += velocity.x
|
||||||
position.y += velocity.dy
|
position.y += velocity.y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,11 +98,11 @@ public class Field {
|
||||||
NSLog("Updating size of field: old:\(parameters.size), new:\(newValue)")
|
NSLog("Updating size of field: old:\(parameters.size), new:\(newValue)")
|
||||||
if parameters.size != newValue {
|
if parameters.size != newValue {
|
||||||
// Scale balls to new position and size.
|
// Scale balls to new position and size.
|
||||||
let scale = parameters.size.width != 0 ? Float(newValue.width / parameters.size.width) : 1
|
let scale = parameters.size.x != 0 ? Float(newValue.x / parameters.size.x) : 1
|
||||||
balls = balls.map {
|
balls = balls.map {
|
||||||
let r = $0.radius * scale
|
let r = $0.radius * scale
|
||||||
let p = randomPoint(forBallWithRadius: r)
|
let p = randomPoint(forBallWithRadius: r)
|
||||||
let v = Vector(dx: $0.velocity.dx * scale, dy: $0.velocity.dy * scale)
|
let v = Float2($0.velocity.x * scale, $0.velocity.y * scale)
|
||||||
return Ball(radius: r, position: p, velocity: v)
|
return Ball(radius: r, position: p, velocity: v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,16 +141,16 @@ public class Field {
|
||||||
|
|
||||||
if !selfBounds.contains(balls[i].position.CGPoint) {
|
if !selfBounds.contains(balls[i].position.CGPoint) {
|
||||||
// Degenerate case. If the ball finds itself outside the bounds of the field, plop it back in the center.
|
// Degenerate case. If the ball finds itself outside the bounds of the field, plop it back in the center.
|
||||||
balls[i].position = Point(x: Float(selfBounds.midX), y: Float(selfBounds.midY))
|
balls[i].position = Float2(x: Float(selfBounds.midX), y: Float(selfBounds.midY))
|
||||||
} else {
|
} else {
|
||||||
// Do collision detection with walls.
|
// Do collision detection with walls.
|
||||||
let ballBounds = balls[i].bounds
|
let ballBounds = balls[i].bounds
|
||||||
if !selfBounds.contains(ballBounds) {
|
if !selfBounds.contains(ballBounds) {
|
||||||
if ballBounds.minX < selfBounds.minX || ballBounds.maxX > selfBounds.maxX {
|
if ballBounds.minX < selfBounds.minX || ballBounds.maxX > selfBounds.maxX {
|
||||||
balls[i].velocity.dx *= -1
|
balls[i].velocity.x *= -1
|
||||||
}
|
}
|
||||||
if ballBounds.minY < selfBounds.minY || ballBounds.maxY > selfBounds.maxY {
|
if ballBounds.minY < selfBounds.minY || ballBounds.maxY > selfBounds.maxY {
|
||||||
balls[i].velocity.dy *= -1
|
balls[i].velocity.y *= -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +163,7 @@ public class Field {
|
||||||
|
|
||||||
let dx = Float(5 - Int(arc4random_uniform(10)))
|
let dx = Float(5 - Int(arc4random_uniform(10)))
|
||||||
let dy = Float(5 - Int(arc4random_uniform(10)))
|
let dy = Float(5 - Int(arc4random_uniform(10)))
|
||||||
let velocity = Vector(dx: dx, dy: dy)
|
let velocity = Float2(dx, dy)
|
||||||
|
|
||||||
let ball = Ball(radius: radius, position: position, velocity: velocity)
|
let ball = Ball(radius: radius, position: position, velocity: velocity)
|
||||||
balls.append(ball)
|
balls.append(ball)
|
||||||
|
|
@ -178,14 +178,14 @@ public class Field {
|
||||||
balls.removeAll(keepingCapacity: true)
|
balls.removeAll(keepingCapacity: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func randomPoint(forBallWithRadius radius: Float) -> Point {
|
private func randomPoint(forBallWithRadius radius: Float) -> Float2 {
|
||||||
guard Float(bounds.width) > radius && Float(bounds.height) > radius else {
|
guard Float(bounds.width) > radius && Float(bounds.height) > radius else {
|
||||||
return Point()
|
return Float2()
|
||||||
}
|
}
|
||||||
let insetBounds = bounds.insetBy(dx: CGFloat(radius), dy: CGFloat(radius))
|
let insetBounds = bounds.insetBy(dx: CGFloat(radius), dy: CGFloat(radius))
|
||||||
let x = Float(UInt32(insetBounds.minX) + arc4random_uniform(UInt32(insetBounds.width)))
|
let x = Float(UInt32(insetBounds.minX) + arc4random_uniform(UInt32(insetBounds.width)))
|
||||||
let y = Float(UInt32(insetBounds.minY) + arc4random_uniform(UInt32(insetBounds.height)))
|
let y = Float(UInt32(insetBounds.minY) + arc4random_uniform(UInt32(insetBounds.height)))
|
||||||
let position = Point(x: x, y: y)
|
let position = Float2(x: x, y: y)
|
||||||
return position
|
return position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +205,7 @@ public class Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let parametersBuffer = parametersBuffer {
|
if let parametersBuffer = parametersBuffer {
|
||||||
parameters.numberOfBalls = UInt16(balls.count)
|
parameters.numberOfBalls = UInt32(balls.count)
|
||||||
self.parameters.write(to: parametersBuffer)
|
self.parameters.write(to: parametersBuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ extension UserDefaults {
|
||||||
public var colorStyle: ColorStyle? {
|
public var colorStyle: ColorStyle? {
|
||||||
get {
|
get {
|
||||||
let value = integer(forKey: "colorStyle")
|
let value = integer(forKey: "colorStyle")
|
||||||
if let colorStyle = ColorStyle(rawValue: UInt16(value)) {
|
if let colorStyle = ColorStyle(rawValue: UInt32(value)) {
|
||||||
return colorStyle
|
return colorStyle
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ public class PreferencesViewController: NSViewController {
|
||||||
func postColorNotification() {
|
func postColorNotification() {
|
||||||
var info = [String:Any]()
|
var info = [String:Any]()
|
||||||
if let item = styleMenu.selectedItem {
|
if let item = styleMenu.selectedItem {
|
||||||
info["colorStyle"] = ColorStyle(rawValue: UInt16(item.tag))
|
info["colorStyle"] = ColorStyle(rawValue: UInt32(item.tag))
|
||||||
}
|
}
|
||||||
for (idx, cv) in colorViews.enumerated() {
|
for (idx, cv) in colorViews.enumerated() {
|
||||||
info["color\(idx)"] = cv.colorWell.color
|
info["color\(idx)"] = cv.colorWell.color
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ public protocol RendererDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
let position: Point
|
let position: Float2
|
||||||
let textureCoordinate: Point
|
let textureCoordinate: Float2
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Renderer: NSObject, MTKViewDelegate {
|
public class Renderer: NSObject, MTKViewDelegate {
|
||||||
|
|
@ -101,13 +101,13 @@ public class Renderer: NSObject, MTKViewDelegate {
|
||||||
|
|
||||||
// Two triangles, plus texture coordinates.
|
// Two triangles, plus texture coordinates.
|
||||||
let points: [Vertex] = [
|
let points: [Vertex] = [
|
||||||
Vertex(position: Point(x: 1, y: -1), textureCoordinate: Point(x: 1, y: 0)),
|
Vertex(position: Float2(x: 1, y: -1), textureCoordinate: Float2(x: 1, y: 0)),
|
||||||
Vertex(position: Point(x: -1, y: -1), textureCoordinate: Point(x: 0, y: 0)),
|
Vertex(position: Float2(x: -1, y: -1), textureCoordinate: Float2(x: 0, y: 0)),
|
||||||
Vertex(position: Point(x: -1, y: 1), textureCoordinate: Point(x: 0, y: 1)),
|
Vertex(position: Float2(x: -1, y: 1), textureCoordinate: Float2(x: 0, y: 1)),
|
||||||
|
|
||||||
Vertex(position: Point(x: 1, y: -1), textureCoordinate: Point(x: 1, y: 0)),
|
Vertex(position: Float2(x: 1, y: -1), textureCoordinate: Float2(x: 1, y: 0)),
|
||||||
Vertex(position: Point(x: -1, y: 1), textureCoordinate: Point(x: 0, y: 1)),
|
Vertex(position: Float2(x: -1, y: 1), textureCoordinate: Float2(x: 0, y: 1)),
|
||||||
Vertex(position: Point(x: 1, y: 1), textureCoordinate: Point(x: 1, y: 1))
|
Vertex(position: Float2(x: 1, y: 1), textureCoordinate: Float2(x: 1, y: 1))
|
||||||
]
|
]
|
||||||
|
|
||||||
field.update()
|
field.update()
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,11 @@ typedef enum {
|
||||||
} ColorStyle;
|
} ColorStyle;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
short2 size;
|
packed_uint2 size;
|
||||||
ushort numberOfBalls;
|
uint numberOfBalls;
|
||||||
|
uint colorStyle;
|
||||||
ushort colorStyle;
|
|
||||||
float target;
|
float target;
|
||||||
float feather;
|
float feather;
|
||||||
|
|
||||||
float4 colors[4];
|
float4 colors[4];
|
||||||
} Parameters;
|
} Parameters;
|
||||||
|
|
||||||
|
|
@ -90,12 +88,12 @@ sampleToColorShader(RasterizerData in [[stage_in]],
|
||||||
out = singleColor(sample, target, feather, parameters.colors[0]);
|
out = singleColor(sample, target, feather, parameters.colors[0]);
|
||||||
break;
|
break;
|
||||||
case Gradient2Horizontal: {
|
case Gradient2Horizontal: {
|
||||||
const float blend = in.position.x / parameters.size.x;
|
const float blend = in.position.x / parameters.size[0];
|
||||||
out = gradient2(sample, target, feather, blend, parameters.colors[0], parameters.colors[1]);
|
out = gradient2(sample, target, feather, blend, parameters.colors[0], parameters.colors[1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Gradient2Vertical: {
|
case Gradient2Vertical: {
|
||||||
const float blend = in.position.y / parameters.size.y;
|
const float blend = in.position.y / parameters.size[1];
|
||||||
out = gradient2(sample, target, feather, blend, parameters.colors[0], parameters.colors[1]);
|
out = gradient2(sample, target, feather, blend, parameters.colors[0], parameters.colors[1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue