texture [[texture(0)]])
40 | {
41 | float4 color = uniforms.u_foregroundColor;
42 | // Outline of glyph is the isocontour with value 50%
43 | float edgeDistance = 0.5;
44 | // Sample the signed-distance field to find distance from this fragment to the glyph outline
45 | float sampleDistance = texture.sample(samplr, vert.texCoords).r;
46 | // Use local automatic gradients to find anti-aliased anisotropic edge width, cf. Gustavson 2012
47 | float edgeWidth = 0.75 * length(float2(dfdx(sampleDistance), dfdy(sampleDistance)));
48 | //float edgeWidth = fwidth(sampleDistance);
49 | // Smooth the glyph edge by interpolating across the boundary in a band with the width determined above
50 | float insideness = smoothstep(edgeDistance - edgeWidth, edgeDistance + edgeWidth, sampleDistance);
51 | return half4(color.r, color.g, color.b, insideness);
52 | //return half4(color.r, color.g, color.b, 1.0);
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/CesiumKit/Core/PixelFormat.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PixelFormat.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 20/07/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import OpenGLES
10 |
11 | enum PixelFormat: Int {
12 | /**
13 | * 0x1902. A pixel format containing a depth value.
14 | *
15 | * @type {Number}
16 | * @constant
17 | */
18 | case DepthComponent = 0x1902,
19 |
20 | /**
21 | * 0x84F9. A pixel format containing a depth and stencil value, most often used with {@link PixelDatatype.UNSIGNED_INT_24_8_WEBGL}.
22 | *
23 | * @type {Number}
24 | * @constant
25 | */
26 | DepthStencil = 0x84F9,
27 |
28 | /**
29 | * 0x1906. A pixel format containing an alpha channel.
30 | *
31 | * @type {Number}
32 | * @constant
33 | */
34 | Alpha = 0x1906,
35 |
36 | /**
37 | * 0x1907. A pixel format containing red, green, and blue channels.
38 | *
39 | * @type {Number}
40 | * @constant
41 | */
42 | RGB = 0x1907,
43 |
44 | /**
45 | * 0x1908. A pixel format containing red, green, blue, and alpha channels.
46 | *
47 | * @type {Number}
48 | * @constant
49 | */
50 | RGBA = 0x1908,
51 |
52 | /**
53 | * 0x1909. A pixel format containing a luminance (intensity) channel.
54 | *
55 | * @type {Number}
56 | * @constant
57 | */
58 | Luminance = 0x1909,
59 |
60 | /**
61 | * 0x190A. A pixel format containing luminance (intensity) and alpha channels.
62 | *
63 | * @type {Number}
64 | * @constant
65 | * @default 0x190A
66 | */
67 | LuminanceAlpha = 0x190A
68 |
69 | func isColorFormat() -> Bool {
70 | return self == PixelFormat.Alpha ||
71 | self == PixelFormat.RGB ||
72 | self == PixelFormat.RGBA ||
73 | self == PixelFormat.Luminance ||
74 | self == PixelFormat.LuminanceAlpha
75 | }
76 |
77 | func isDepthFormat() -> Bool {
78 | return self == PixelFormat.DepthComponent ||
79 | self == PixelFormat.DepthStencil
80 | }
81 | }
--------------------------------------------------------------------------------
/CesiumKit/Renderer/PassState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PassState.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 15/06/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import Metal
10 |
11 | /**
12 | * The state for a particular rendering pass. This is used to supplement the state
13 | * in a command being executed.
14 | *
15 | * @private
16 | */
17 | class PassState {
18 | /**
19 | * The context used to execute commands for this pass.
20 | *
21 | * @type {Context}
22 | */
23 | weak var context: Context! = nil
24 |
25 | /**
26 | * The framebuffer to render to. This framebuffer is used unless a {@link DrawCommand}
27 | * or {@link ClearCommand} explicitly define a framebuffer, which is used for off-screen
28 | * rendering.
29 | *
30 | * @type {Framebuffer}
31 | * @default undefined
32 | */
33 | var framebuffer: Framebuffer! = nil
34 |
35 | /**
36 | * When defined, this overrides the blending property of a {@link DrawCommand}'s render state.
37 | * This is used to, for example, to allow the renderer to turn off blending during the picking pass.
38 | *
39 | * When this is undefined, the {@link DrawCommand}'s property is used.
40 | *
41 | *
42 | * @type {Boolean}
43 | * @default undefined
44 | */
45 | var blendingEnabled: Bool? = nil
46 |
47 | /**
48 | * When defined, this overrides the scissor test property of a {@link DrawCommand}'s render state.
49 | * This is used to, for example, to allow the renderer to scissor out the pick region during the picking pass.
50 | *
51 | * When this is undefined, the {@link DrawCommand}'s property is used.
52 | *
53 | *
54 | * @type {Object}
55 | * @default undefined
56 | */
57 | var scissorTest: RenderState.ScissorTest? = nil
58 |
59 | /**
60 | * The viewport used when one is not defined by a {@link DrawCommand}'s render state.
61 | * @type {BoundingRectangle}
62 | * @default undefined
63 | */
64 | var viewport: Cartesian4? = nil
65 |
66 | }
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/UniformMap.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UniformMap.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 27/02/15.
6 | // Copyright (c) 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | protocol UniformStruct {
10 |
11 | }
12 |
13 | typealias UniformUpdateBlock = ((_ buffer: Buffer) -> [Texture])
14 |
15 | typealias UniformMapDeallocBlock = (UniformBufferProvider) -> Void
16 |
17 | struct UniformDescriptor {
18 | let name: String
19 | let type: UniformDataType
20 | let count: Int
21 |
22 | func declaration () -> String {
23 | var declaration = "\(type.metalDeclaration) \(name)"
24 |
25 | if count == 1 {
26 | declaration += ";"
27 | } else {
28 | declaration += "[\(count)];"
29 | }
30 |
31 | return declaration
32 | }
33 | }
34 |
35 | protocol UniformMap: class {
36 |
37 | var uniformBufferProvider: UniformBufferProvider! { get set }
38 |
39 | var uniformDescriptors: [UniformDescriptor] { get }
40 | }
41 |
42 | protocol NativeUniformMap: class, UniformMap {
43 |
44 | var uniformUpdateBlock: UniformUpdateBlock { get }
45 |
46 | func generateMetalUniformStruct () -> String
47 | }
48 |
49 | extension NativeUniformMap {
50 |
51 | func generateMetalUniformStruct () -> String {
52 |
53 | let prefix = "struct xlatMtlShaderUniform {\n"
54 | let suffix = "};\n"
55 | let uniformDefinitions = uniformDescriptors.reduce(prefix) { $0 + " \($1.declaration())\n" }
56 |
57 | return uniformDefinitions + suffix
58 | }
59 | }
60 |
61 | protocol LegacyUniformMap: class, UniformMap {
62 |
63 | var uniforms: [String: UniformFunc] { get }
64 |
65 | func indexForUniform(_ name: String) -> UniformIndex?
66 |
67 | func uniform(_ index: UniformIndex) -> UniformFunc
68 |
69 | func textureForUniform (_ uniform: UniformSampler) -> Texture?
70 | }
71 |
72 | extension LegacyUniformMap {
73 |
74 | func indexForUniform(_ name: String) -> UniformIndex? {
75 | return uniforms.index(forKey: name)
76 | }
77 |
78 | func uniform(_ index: UniformIndex) -> UniformFunc {
79 | return uniforms[index].1
80 | }
81 |
82 | func textureForUniform (_ uniform: UniformSampler) -> Texture? {
83 | return nil
84 | }
85 |
86 | }
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/CesiumKit/Platform/String.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 28/11/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum ObjectSourceReferenceType {
12 | case bundleResource
13 | case networkURL
14 | case filePath
15 | }
16 |
17 | extension String {
18 | subscript (r: Range) -> String {
19 | get {
20 | let startIndex = self.characters.index(self.startIndex, offsetBy: r.lowerBound)
21 | let endIndex = self.characters.index(self.startIndex, offsetBy: r.upperBound - r.lowerBound)
22 |
23 | return String(self[startIndex.. String {
28 | return self.replacingOccurrences(of: existingString, with: newString, options: .literal, range: nil)
29 | }
30 |
31 | func indexOf(_ findStr:String, startIndex: String.Index? = nil) -> String.Index? {
32 | return self.range(of: findStr, options: [], range: nil, locale: nil)?.lowerBound
33 | }
34 |
35 | }
36 | // FIXME: move to cubemap
37 | extension String {
38 | var referenceType: ObjectSourceReferenceType {
39 | if self.hasPrefix("/") {
40 | return .filePath
41 | } else if self.hasPrefix("http") {
42 | return .networkURL
43 | }
44 | return .bundleResource
45 | }
46 |
47 |
48 | func urlForSource () -> URL? {
49 | switch self.referenceType {
50 | case .bundleResource:
51 | let bundle = Bundle(identifier: "com.testtoast.CesiumKit") ?? Bundle.main
52 | return bundle.url(forResource: (self as NSString).deletingPathExtension, withExtension: (self as NSString).pathExtension)
53 | case .filePath:
54 | return URL(fileURLWithPath: self, isDirectory: false)
55 | case .networkURL:
56 | return URL(string: self)
57 | }
58 | }
59 |
60 | func loadImageForCubeMapSource () -> CGImage? {
61 |
62 | guard let sourceURL = urlForSource() else {
63 | return nil
64 | }
65 | do {
66 | let data = try Data(contentsOf: sourceURL, options: [])
67 | return CGImage.from(data)
68 | } catch {
69 | return nil
70 | }
71 |
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/CesiumKit/Core/HeadingPitchRange.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HeadingPitchRange.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 15/03/15.
6 | // Copyright (c) 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | * Defines a heading angle, pitch angle an range in a local frame.
13 | * Heading is the rotation from the local north direction where a positive angle is increasing eastward.
14 | * Pitch is the rotation from the local xy-plane. Positive pitch angles are above the plane. Negative pitch
15 | * angles are below the plane. Range is the distance from the center of the frame.
16 | * @alias HeadingPitchRange
17 | * @constructor
18 | *
19 | * @param {Number} [heading=0.0] The heading angle in radians.
20 | * @param {Number} [pitch=0.0] The pitch angle in radians.
21 | * @param {Number} [range=0.0] The distance from the center in meters.
22 | */
23 |
24 | public struct HeadingPitchRange {
25 |
26 | /**
27 | * Heading is the rotation from the local north direction where a positive angle is increasing eastward.
28 | * @type {Number}
29 | */
30 | public var heading: Double = 0.0
31 |
32 | /**
33 | * Pitch is the rotation from the local xy-plane. Positive pitch angles
34 | * are above the plane. Negative pitch angles are below the plane.
35 | * @type {Number}
36 | */
37 | public var pitch: Double = 0.0
38 |
39 | /**
40 | * Range is the distance from the center of the local frame.
41 | * @type {Number}
42 | */
43 | public var range: Double = 0.0
44 |
45 | public init (heading: Double = 0.0, pitch: Double = 0.0, range: Double = 0.0) {
46 | self.heading = heading
47 | self.pitch = pitch
48 | self.range = range
49 | }
50 | }
51 |
52 | extension HeadingPitchRange: Offset {
53 |
54 | public var offset: Cartesian3 {
55 | let pitch = Math.clamp(self.pitch, min: -.pi/2, max: .pi/2)
56 | let heading = Math.zeroToTwoPi(self.heading) - .pi/2
57 |
58 | let pitchQuat = Quaternion(axis: Cartesian3.unitY, angle: -pitch)
59 | let headingQuat = Quaternion(axis: Cartesian3.unitZ, angle: -heading)
60 | let rotQuat = headingQuat.multiply(pitchQuat)
61 | let rotMatrix = Matrix3(quaternion: rotQuat)
62 |
63 | let offset = rotMatrix
64 | .multiplyByVector(Cartesian3.unitX)
65 | .negate()
66 | .multiplyBy(scalar: range)
67 | return offset
68 | }
69 |
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/CesiumKit/Platform/Crypto.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Crypto.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 13/04/2016.
6 | // Copyright © 2016 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CommonCrypto
11 |
12 | public struct HMAC {
13 |
14 | static func hash(_ inp: String, algo: HMACAlgo) -> String {
15 | if let stringData = inp.data(using: String.Encoding.utf8, allowLossyConversion: false) {
16 | return hexStringFromBuffer(digest(stringData, algo: algo))
17 | }
18 | return ""
19 | }
20 |
21 | fileprivate static func digest(_ input: Data, algo: HMACAlgo) -> [UInt8] {
22 | let digestLength = algo.digestLength()
23 | var hash = [UInt8](repeating: 0, count: digestLength)
24 | input.withUnsafeBytes { (pointer: UnsafePointer) in
25 | switch algo {
26 | case .md5:
27 | CC_MD5(pointer, UInt32(input.count), &hash)
28 | break
29 | case .sha1:
30 | CC_SHA1(pointer, UInt32(input.count), &hash)
31 | break
32 | case .sha224:
33 | CC_SHA224(pointer, UInt32(input.count), &hash)
34 | break
35 | case .sha256:
36 | CC_SHA256(pointer, UInt32(input.count), &hash)
37 | break
38 | case .sha384:
39 | CC_SHA384(pointer, UInt32(input.count), &hash)
40 | break
41 | case .sha512:
42 | CC_SHA512(pointer, UInt32(input.count), &hash)
43 | break
44 | }
45 | }
46 | return hash
47 | }
48 |
49 | fileprivate static func hexStringFromBuffer(_ input: [UInt8]) -> String {
50 | return input.reduce("") { $0 + String(format:"%02x", $1) }
51 | }
52 | }
53 |
54 | enum HMACAlgo {
55 | case md5, sha1, sha224, sha256, sha384, sha512
56 |
57 | func digestLength() -> Int {
58 | var result: CInt = 0
59 | switch self {
60 | case .md5:
61 | result = CC_MD5_DIGEST_LENGTH
62 | case .sha1:
63 | result = CC_SHA1_DIGEST_LENGTH
64 | case .sha224:
65 | result = CC_SHA224_DIGEST_LENGTH
66 | case .sha256:
67 | result = CC_SHA256_DIGEST_LENGTH
68 | case .sha384:
69 | result = CC_SHA384_DIGEST_LENGTH
70 | case .sha512:
71 | result = CC_SHA512_DIGEST_LENGTH
72 | }
73 | return Int(result)
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/CesiumKitRunner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // AppDelegate.swift
4 | // CesiumKitRunner
5 | //
6 | // Created by Ryan Walklin on 10/12/14.
7 | // Copyright (c) 2014 Test Toast. All rights reserved.
8 | //
9 |
10 | import UIKit
11 | import CesiumKit
12 |
13 | @UIApplicationMain
14 | class AppDelegate: UIResponder, UIApplicationDelegate {
15 |
16 | var window: UIWindow?
17 |
18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | //if let view = self.window?.rootViewController?.view as? MetalView {
26 | // view.render = false
27 | //}
28 | }
29 |
30 | func applicationDidEnterBackground(application: UIApplication) {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 | func applicationWillEnterForeground(application: UIApplication) {
36 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
37 | }
38 |
39 | func applicationDidBecomeActive(application: UIApplication) {
40 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
41 | //if let view = self.window?.rootViewController?.view as? MetalView {
42 | // view.render = true
43 | //}
44 | }
45 |
46 | func applicationWillTerminate(application: UIApplication) {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/CesiumKit/Core/Credit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Credit.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 12/06/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | private var _nextCreditId = 0
10 | private var _creditToId = [String: Int]()
11 |
12 | /**
13 | * A credit contains data pertaining to how to display attributions/credits for certain content on the screen.
14 | *
15 | * @param {String} [text] The text to be displayed on the screen if no imageUrl is specified.
16 | * @param {String} [imageUrl] The source location for an image
17 | * @param {String} [link] A URL location for which the credit will be hyperlinked
18 | *
19 | * @alias Credit
20 | * @constructor
21 | *
22 | * @example
23 | * //Create a credit with a tooltip, image and link
24 | * var credit = new Cesium.Credit('Cesium', '/images/cesium_logo.png', 'http://cesiumjs.org/');
25 | */
26 | public struct Credit: Equatable {
27 |
28 | public let text: String?
29 |
30 | public let imageUrl: String?
31 |
32 | public let link: String?
33 |
34 | var hasText: Bool {
35 | return text != nil
36 | }
37 |
38 | var hasImage: Bool {
39 | return imageUrl != nil
40 | }
41 |
42 | var hasLink: Bool {
43 | return link != nil
44 | }
45 |
46 | /**
47 | * @memberof Credit.prototype
48 | * @type {Number}
49 | *
50 | * @private
51 | */
52 | let id: Int
53 |
54 | init (text: String? = nil, imageUrl: String? = nil, link: String? = nil) {
55 | assert(text != nil || imageUrl != nil || link != nil, "text, imageUrl or link is required")
56 |
57 | if (text == nil && imageUrl == nil) {
58 | self.text = link
59 | } else {
60 | self.text = text
61 | }
62 | self.imageUrl = imageUrl
63 | self.link = link
64 |
65 | // Credits are immutable so generate an id to use to optimize equal()
66 | let key = "[\(text ?? ""):\(imageUrl ?? ""):\(link ?? "")]"
67 | if let creditToId = _creditToId[key] {
68 | id = creditToId
69 | } else {
70 | id = _nextCreditId
71 | _creditToId[key] = id
72 | _nextCreditId += 1
73 | }
74 | }
75 | }
76 | /**
77 | * Returns true if the credits are equal
78 | *
79 | * @param {Credit} left The first credit
80 | * @param {Credit} left The second credit
81 | * @returns {Boolean} true if left and right are equal, false otherwise.
82 | */
83 |
84 | public func == (left: Credit, right: Credit) -> Bool {
85 | return left.id == right.id
86 | }
87 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/MaterialType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MaterialType.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 31/01/2016.
6 | // Copyright © 2016 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import simd
11 |
12 | public protocol MaterialType {
13 | var name: String { get }
14 | var fabric: FabricDescription { get }
15 | var source: String? { get }
16 | var components: [String: String] { get }
17 | var translucent: (Material) -> Bool { get }
18 | }
19 |
20 | public struct ColorMaterialType: MaterialType {
21 |
22 | public let name = "Color"
23 |
24 | public var fabric: FabricDescription
25 |
26 | public var source: String? = nil
27 |
28 | public let components = [
29 | "diffuse": "u_color.rgb",
30 | "alpha": "u_color.a"
31 | ]
32 |
33 | public let translucent = { (material: Material) in
34 | return (material.type.fabric as! ColorFabricDescription).color.alpha < 1.0
35 | }
36 |
37 | public init (fabric: ColorFabricDescription = ColorFabricDescription(), source: String? = nil) {
38 | self.fabric = fabric
39 | self.source = source
40 | }
41 | }
42 |
43 | open class FabricDescription {
44 | var uniformMap: LegacyUniformMap! {
45 | assertionFailure("invalid base class")
46 | return nil
47 | }
48 | }
49 |
50 | open class ColorFabricDescription: FabricDescription {
51 |
52 | open var color: Color {
53 | get {
54 | return _uniformMap.color
55 | }
56 | set {
57 | _uniformMap.color = newValue
58 | }
59 | }
60 |
61 | override var uniformMap: LegacyUniformMap {
62 | return _uniformMap
63 | }
64 |
65 | fileprivate let _uniformMap = ColorFabricUniformMap()
66 |
67 | public override init () {
68 |
69 | }
70 | }
71 |
72 | class ColorFabricUniformMap: LegacyUniformMap {
73 |
74 | var color = Color()
75 |
76 | var uniformBufferProvider: UniformBufferProvider! = nil
77 |
78 | let uniforms: [String: UniformFunc] = [
79 | "u_color": { map, buffer, offset in
80 | let simd = (map as! ColorFabricUniformMap).color.floatRepresentation
81 | buffer.write(from: [simd], length: MemoryLayout.size(ofValue: simd))
82 | }
83 | ]
84 |
85 | let uniformDescriptors = [
86 | UniformDescriptor(name: "u_color", type: .floatVec4, count: 1)
87 | ]
88 | }
89 |
90 |
91 |
92 |
93 |
94 | open class ImageFabricDescription: FabricDescription {
95 |
96 | //var uniformMap: UniformMap = NullUniformMap()
97 |
98 | //public var uniforms: [String: UniformFunc]
99 |
100 | //public var uniformTypes: [String : UniformDataType]
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/CesiumKit/Core/Queue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Queue.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 27/09/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 |
10 | /**
11 | * A queue that can enqueue items at the end, and dequeue items from the front.
12 | *
13 | * @alias Queue
14 | * @constructor
15 | */
16 | class Queue {
17 | fileprivate var _array = [T]()
18 |
19 | /**
20 | * Enqueues the specified item.
21 | *
22 | * @param {Object} item The item to enqueue.
23 | */
24 | func enqueue(_ item: T) {
25 | _array.append(item)
26 | }
27 |
28 | /**
29 | * Dequeues an item. Returns undefined if the queue is empty.
30 | */
31 | func dequeue() -> T? {
32 | if _array.count == 0 {
33 | return nil
34 | }
35 | return _array.remove(at: 0)
36 | }
37 |
38 | var head: T? {
39 | get {
40 | if _array.count == 0 {
41 | return nil
42 | }
43 | return _array[0]
44 | }
45 | }
46 |
47 | var tail: T? {
48 | get {
49 | return _array.last
50 | }
51 | }
52 |
53 | var count: Int {
54 | get {
55 | return _array.count
56 | }
57 | }
58 |
59 | /**
60 | * Check whether this queue contains the specified item.
61 | *
62 | * @param {Object} item the item to search for.
63 | */
64 | func contains(_ item: T) -> Bool {
65 | for object in _array {
66 | if object == item {
67 | return true
68 | }
69 | }
70 | return false
71 | }
72 |
73 | /**
74 | * Remove all items from the queue.
75 | */
76 | func clear() {
77 | _array.removeAll()
78 | }
79 |
80 | /*
81 | /**
82 | * Sort the items in the queue in-place.
83 | *
84 | * @param {Queue~Comparator} compareFunction A function that defines the sort order.
85 | */
86 | Queue.prototype.sort = function(compareFunction) {
87 | if (this._offset > 0) {
88 | //compact array
89 | this._array = this._array.slice(this._offset);
90 | this._offset = 0;
91 | }
92 |
93 | this._array.sort(compareFunction);
94 | };
95 | */
96 | /**
97 | * A function used to compare two items while sorting a queue.
98 | * @callback Queue~Comparator
99 | *
100 | * @param {Object} a An item in the array.
101 | * @param {Object} b An item in the array.
102 | * @returns {Number} Returns a negative value if a is less than b,
103 | * a positive value if a is greater than b, or
104 | * 0 if a is equal to b.
105 | *
106 | * @example
107 | * function compareNumbers(a, b) {
108 | * return a - b;
109 | * }
110 | */
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/CesiumKit/Core/TimeConstants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TimeConstants.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 10/12/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | * Constants for time conversions like those done by {@link JulianDate}.
13 | *
14 | * @namespace
15 | * @alias TimeConstants
16 | *
17 | * @see JulianDate
18 | *
19 | * @private
20 | */
21 | struct TimeConstants {
22 |
23 | /**
24 | * The number of seconds in one millisecond: 0.001
25 | * @type {Number}
26 | * @constant
27 | */
28 | static let SecondsPerMillisecond: Double = 0.001
29 |
30 | /**
31 | * The number of seconds in one millisecond: 0.001
32 | * @type {Number}
33 | * @constant
34 | */
35 | static let SecondsPerNanosecond: Double = 0.000000001
36 |
37 | /**
38 | * The number of seconds in one minute: 60.
39 | * @type {Number}
40 | * @constant
41 | */
42 | static let SecondsPerMinute: Double = 60.0
43 |
44 | /**
45 | * The number of minutes in one hour: 60.
46 | * @type {Number}
47 | * @constant
48 | */
49 | static let MinutesPerHour: Double = 60.0
50 |
51 | /**
52 | * The number of hours in one day: 24.
53 | * @type {Number}
54 | * @constant
55 | */
56 | static let HoursPerDay: Double = 24.0
57 |
58 | /**
59 | * The number of seconds in one hour: 3600.
60 | * @type {Number}
61 | * @constant
62 | */
63 | static let SecondsPerHour: Double = 3600.0
64 |
65 | /**
66 | * The number of minutes in one day: 1440.
67 | * @type {Number}
68 | * @constant
69 | */
70 | static let MinutesPerDay: Double = 1440.0
71 |
72 | /**
73 | * The number of seconds in one day, ignoring leap seconds: 86400.
74 | * @type {Number}
75 | * @constant
76 | */
77 | static let SecondsPerDay: Double = 86400.0
78 |
79 | /**
80 | * The number of days in one Julian century: 36525.
81 | * @type {Number}
82 | * @constant
83 | */
84 | static let DaysPerJulianCentury: Double = 36525.0
85 |
86 | /**
87 | * One trillionth of a second.
88 | * @type {Number}
89 | * @constant
90 | */
91 | static let PicoSecond: Double = 0.000000001
92 |
93 | /**
94 | * The number of days to subtract from a Julian date to determine the
95 | * modified Julian date, which gives the number of days since midnight
96 | * on November 17, 1858.
97 | * @type {Number}
98 | * @constant
99 | */
100 | static let ModifiedJulianDateDifference: Double = 2400000.5
101 |
102 | /**
103 | The number of days between the Julian epoch (4713-1-1 BCE) since the OS X reference date (2001-01-01T00:00Z)
104 | */
105 | static let JulianEpochToMacEpochDifference: Double = 2451910.5
106 |
107 | }
--------------------------------------------------------------------------------
/CesiumKit.xcodeproj/xcshareddata/xcschemes/CesiumKit.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
55 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
76 |
77 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/RenderPipeline.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RenderPipeline.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 31/05/2015.
6 | // Copyright (c) 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Metal
10 |
11 | class RenderPipeline {
12 |
13 | let state: MTLRenderPipelineState!
14 |
15 | let shaderProgram: ShaderProgram
16 |
17 | var keyword: String {
18 | return state.label ?? ""
19 | }
20 |
21 | var blendingState: BlendingState? = nil
22 |
23 | var count: Int = 0
24 |
25 | fileprivate var _descriptor: MTLRenderPipelineDescriptor
26 |
27 | init (device: MTLDevice, shaderProgram: ShaderProgram, descriptor: MTLRenderPipelineDescriptor) {
28 |
29 | self.shaderProgram = shaderProgram
30 | _descriptor = descriptor
31 | do {
32 | let state = try device.makeRenderPipelineState(descriptor: _descriptor)
33 | self.state = state
34 | } catch let error as NSError {
35 | state = nil
36 | assertionFailure("makeRenderPipelineState failed: \(error.localizedDescription)")
37 | }
38 | }
39 |
40 | static func fromCache (context: Context, vertexShaderSource vss: ShaderSource, fragmentShaderSource fss: ShaderSource, vertexDescriptor vd: VertexDescriptor?, colorMask: ColorMask? = nil, depthStencil: Bool, blendingState: BlendingState? = nil, manualUniformStruct: String? = nil, uniformStructSize: Int? = nil) -> RenderPipeline {
41 | //FIXME: remove nil for manualUniformStruct
42 | return context.pipelineCache.getRenderPipeline(vertexShaderSource: vss, fragmentShaderSource: fss, vertexDescriptor: vd, colorMask: colorMask, depthStencil: depthStencil, blendingState: blendingState, manualUniformStruct: manualUniformStruct, uniformStructSize: uniformStructSize)
43 | }
44 |
45 | static func replaceCache (context: Context, pipeline: RenderPipeline?, vertexShaderSource vss: ShaderSource, fragmentShaderSource fss: ShaderSource, vertexDescriptor vd: VertexDescriptor?, colorMask: ColorMask? = nil, depthStencil: Bool, blendingState: BlendingState? = nil) -> RenderPipeline? {
46 |
47 | return context.pipelineCache.replaceRenderPipeline(pipeline, vertexShaderSource: vss, fragmentShaderSource: fss, vertexDescriptor: vd, colorMask: colorMask, depthStencil: depthStencil, blendingState: blendingState)
48 | }
49 |
50 | static func withCompiledShader(_ context: Context, shaderSourceName: String, compiledMetalVertexName vertex: String, compiledMetalFragmentName fragment: String, uniformStructSize: Int, vertexDescriptor vd: VertexDescriptor?, colorMask: ColorMask? = nil, depthStencil: Bool, blendingState: BlendingState? = nil) -> RenderPipeline? {
51 | return context.pipelineCache.getRenderPipeline(shaderSourceName: shaderSourceName, compiledMetalVertexName: vertex, compiledMetalFragmentName: fragment, uniformStructSize: uniformStructSize, vertexDescriptor: vd, colorMask: colorMask, depthStencil: depthStencil, blendingState: blendingState)
52 | }
53 |
54 | func setUniforms(_ command: DrawCommand, device: MTLDevice, uniformState: UniformState) -> (fragmentOffset: Int, texturesValid: Bool, textures: [Texture]) {
55 | return shaderProgram.setUniforms(command, uniformState: uniformState)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/CesiumKit/Core/ScreenSpaceEventType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ScreenSpaceEventType.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 28/03/2015.
6 | // Copyright (c) 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | /**
10 | * This enumerated type is for classifying mouse events: down, up, click, double click, move and move while a button is held down.
11 | *
12 | * @namespace
13 | * @alias ScreenSpaceEventType
14 | */
15 | enum ScreenSpaceEventType: Int {
16 | /**
17 | * Represents a mouse left button down event.
18 | *
19 | * @type {Number}
20 | * @constant
21 | */
22 | case leftDown = 0,
23 |
24 | /**
25 | * Represents a mouse left button up event.
26 | *
27 | * @type {Number}
28 | * @constant
29 | */
30 | leftUp,
31 |
32 | /**
33 | * Represents a mouse left click event.
34 | *
35 | * @type {Number}
36 | * @constant
37 | */
38 | leftClick,
39 |
40 | /**
41 | * Represents a mouse left double click event.
42 | *
43 | * @type {Number}
44 | * @constant
45 | */
46 | leftDoubleClick,
47 |
48 | /**
49 | * Represents a mouse left button down event.
50 | *
51 | * @type {Number}
52 | * @constant
53 | */
54 | rightDown,
55 |
56 | /**
57 | * Represents a mouse right button up event.
58 | *
59 | * @type {Number}
60 | * @constant
61 | */
62 | rightUp,
63 |
64 | /**
65 | * Represents a mouse right click event.
66 | *
67 | * @type {Number}
68 | * @constant
69 | */
70 | rightClick,
71 |
72 | /**
73 | * Represents a mouse right double click event.
74 | *
75 | * @type {Number}
76 | * @constant
77 | */
78 | rightDoubleClick,
79 |
80 | /**
81 | * Represents a mouse middle button down event.
82 | *
83 | * @type {Number}
84 | * @constant
85 | */
86 | middleDown,
87 |
88 | /**
89 | * Represents a mouse middle button up event.
90 | *
91 | * @type {Number}
92 | * @constant
93 | */
94 | middleUp,
95 |
96 | /**
97 | * Represents a mouse middle click event.
98 | *
99 | * @type {Number}
100 | * @constant
101 | */
102 | middleClick,
103 |
104 | /**
105 | * Represents a mouse middle double click event.
106 | *
107 | * @type {Number}
108 | * @constant
109 | */
110 | middleDoubleClick,
111 |
112 | /**
113 | * Represents a mouse move event.
114 | *
115 | * @type {Number}
116 | * @constant
117 | */
118 | mouseMove,
119 |
120 | /**
121 | * Represents a mouse wheel event.
122 | *
123 | * @type {Number}
124 | * @constant
125 | */
126 | wheel,
127 |
128 | /**
129 | * Represents the start of a two-finger event on a touch surface.
130 | *
131 | * @type {Number}
132 | * @constant
133 | */
134 | pinchStart,
135 |
136 | /**
137 | * Represents the end of a two-finger event on a touch surface.
138 | *
139 | * @type {Number}
140 | * @constant
141 | */
142 | pinchEnd,
143 |
144 | /**
145 | * Represents a change of a two-finger event on a touch surface.
146 | *
147 | * @type {Number}
148 | * @constant
149 | */
150 | pinchMove
151 | }
152 |
--------------------------------------------------------------------------------
/CesiumKit/Platform/Array.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Array.swift
3 | // Cent
4 | //
5 | // Created by Ankur Patel on 6/28/14.
6 | // Copyright (c) 2014 Encore Dev Labs LLC. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public func deleteDuplicates(_ seq:S)-> S where S.Iterator.Element: Equatable {
12 | let s = seq.reduce(S()){
13 | ac, x in ac.contains(x) ? ac : ac + [x]
14 | }
15 | return s
16 | }
17 |
18 | extension Array {
19 | var sizeInBytes: Int {
20 | return count == 0 ? 0 : count * MemoryLayout.stride(ofValue: self[0])
21 | }
22 |
23 | /**
24 | * Finds an item in a sorted array.
25 | *
26 | * @exports binarySearch
27 | *
28 | * @param {Array} array The sorted array to search.
29 | * @param {Object} itemToFind The item to find in the array.
30 | * @param {binarySearch~Comparator} comparator The function to use to compare the item to
31 | * elements in the array.
32 | * @returns {Number} The index of itemToFind in the array, if it exists. If itemToFind
33 | * does not exist, the return value is a negative number which is the bitwise complement (~)
34 | * of the index before which the itemToFind should be inserted in order to maintain the
35 | * sorted order of the array.
36 | *
37 | * @example
38 | * // Create a comparator function to search through an array of numbers.
39 | * var comparator = function(a, b) {
40 | * return a - b;
41 | * };
42 | * var numbers = [0, 2, 4, 6, 8];
43 | * var index = Cesium.binarySearch(numbers, 6, comparator); // 3
44 | */
45 | func binarySearch (_ itemToFind: Element, comparator: BinarySearchComparator) -> Int {
46 | var low = 0
47 | var high = self.count - 1
48 | var i: Int
49 | var comparison: Int
50 |
51 | while low <= high {
52 | i = Int(trunc(Double(low + high) / 2.0))
53 | comparison = comparator(self[i], itemToFind)
54 | if comparison < 0 {
55 | low = i + 1
56 | continue
57 | }
58 | if comparison > 0 {
59 | high = i - 1
60 | continue
61 | }
62 | return i;
63 | }
64 | return ~(high + 1)
65 | }
66 |
67 | /**
68 | * A function used to compare two items while performing a binary search.
69 | * @callback binarySearch~Comparator
70 | *
71 | * @param {Object} a An item in the array.
72 | * @param {Object} b The item being searched for.
73 | * @returns {Number} Returns a negative value if a is less than b,
74 | * a positive value if a is greater than b, or
75 | * 0 if a is equal to b.
76 | *
77 | * @example
78 | * function compareNumbers(a, b) {
79 | * return a - b;
80 | * }
81 | */
82 | typealias BinarySearchComparator = (_ a: Element, _ b: Element) -> Int
83 |
84 | }
85 |
86 | extension Array where Element: Equatable {
87 |
88 | // Remove first collection element that is equal to the given `object`:
89 | mutating func removeObject(object: Element) {
90 | if let index = index(of: object) {
91 | remove(at: index)
92 | }
93 | }
94 | }
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/Imagery.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Imagery.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 16/08/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | * Stores details about a tile of imagery.
13 | *
14 | * @alias Imagery
15 | * @private
16 | */
17 | class Imagery {
18 |
19 | unowned var imageryLayer: ImageryLayer
20 |
21 | var level: Int
22 |
23 | var x: Int
24 |
25 | var y: Int
26 |
27 | var parent: Imagery? = nil
28 |
29 | var rectangle: Rectangle? = nil
30 |
31 | var image: CGImage? = nil
32 |
33 | var imageUrl: String? = nil
34 |
35 | var state: ImageryState = .unloaded
36 |
37 | var texture: Texture? = nil
38 |
39 | var reprojectCommand: DrawCommand? = nil
40 |
41 | var credits = [Credit]()
42 |
43 | fileprivate var _referenceCount: Int = 0
44 |
45 | init(imageryLayer: ImageryLayer, level: Int, x: Int, y: Int, rectangle: Rectangle? = nil) {
46 |
47 | self.imageryLayer = imageryLayer
48 | self.level = level
49 | self.x = x
50 | self.y = y
51 |
52 | if (level != 0) {
53 | let parentX = x / 2 | 0
54 | let parentY = y / 2 | 0
55 | let parentLevel = level - 1
56 | parent = imageryLayer.getImageryFromCache(level: parentLevel, x: parentX, y: parentY)
57 | }
58 |
59 | if rectangle == nil && imageryLayer.imageryProvider.ready {
60 | let tilingScheme = imageryLayer.imageryProvider.tilingScheme
61 | self.rectangle = tilingScheme.tileXYToRectangle(x: x, y: y, level: level)
62 | } else {
63 | self.rectangle = rectangle
64 | }
65 | }
66 |
67 | class func createPlaceholder(_ imageryLayer: ImageryLayer) -> Imagery {
68 | let result = Imagery(imageryLayer: imageryLayer, level: 0, x: 0, y: 0)
69 | result.addReference()
70 | result.state = .placeHolder
71 | return result
72 | }
73 |
74 | func addReference() {
75 | _referenceCount += 1
76 | }
77 |
78 | func releaseReference() -> Int {
79 | _referenceCount -= 1
80 |
81 | if _referenceCount == 0 {
82 | imageryLayer.removeImageryFromCache(self)
83 |
84 | if parent != nil {
85 | parent!.releaseReference()
86 | }
87 | return 0
88 | }
89 | return _referenceCount
90 | }
91 |
92 | func processStateMachine (frameState: inout FrameState) {
93 | if (state == .unloaded) {
94 | state = .transitioning
95 | imageryLayer.requestImagery(self)
96 | }
97 | if (state == .received) {
98 | state = .transitioning
99 | imageryLayer.createTexture(frameState: frameState, imagery: self)
100 | }
101 | if (state == .textureLoaded) {
102 | state = .transitioning
103 | imageryLayer.reprojectTexture(frameState: &frameState, imagery: self)
104 | }
105 | if (state == .reprojected) {
106 | state = .transitioning
107 | imageryLayer.generateMipmaps(frameState: &frameState, imagery: self)
108 | }
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/Buffer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Buffer.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 26/05/2015.
6 | // Copyright (c) 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Metal
10 |
11 | class Buffer {
12 |
13 | let metalBuffer: MTLBuffer
14 |
15 | var componentDatatype: ComponentDatatype
16 |
17 | // bytes
18 | let length: Int
19 |
20 | fileprivate let _entireRange: Range
21 |
22 | var count: Int {
23 | return length / componentDatatype.elementSize
24 | }
25 |
26 | /**
27 | Creates a Metal GPU buffer. If an allocated memory region is passed in, it will be
28 | copied to the buffer and can be released (or automatically released via ARC).
29 | */
30 | init? (device: MTLDevice, array: UnsafeRawPointer? = nil, componentDatatype: ComponentDatatype, sizeInBytes: Int, label: String? = nil) {
31 | assert(sizeInBytes > 0, "bufferSize must be greater than zero")
32 |
33 | length = sizeInBytes
34 | self.componentDatatype = componentDatatype
35 | _entireRange = 0..? = nil) {
82 | #if os(OSX)
83 | metalBuffer.didModifyRange(range ?? _entireRange)
84 | #endif
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/ClearCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 15/06/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import Metal
10 |
11 | /**
12 | * Represents a command to the renderer for clearing a framebuffer.
13 | *
14 | * @private
15 | */
16 | struct ClearCommand {
17 |
18 | let boundingVolume: BoundingVolume? = nil
19 | let cull: Bool = false
20 |
21 | /**
22 | * The value to clear the color buffer to. When undefined, the color buffer is not cleared.
23 | *
24 | * @type {Color}
25 | *
26 | * @default undefined
27 | */
28 | var color: Color?
29 |
30 | /**
31 | * The value to clear the depth buffer to. When undefined, the depth buffer is not cleared.
32 | *
33 | * @type {Number}
34 | *
35 | * @default undefined
36 | */
37 | var depth: Double?
38 |
39 | /**
40 | * The value to clear the stencil buffer to. When undefined, the stencil buffer is not cleared.
41 | *
42 | * @type {Number}
43 | *
44 | * @default undefined
45 | */
46 | var stencil: UInt32?
47 |
48 | /**
49 | * The render state to apply when executing the clear command. The following states affect clearing:
50 | * scissor test, color mask, depth mask, and stencil mask. When the render state is
51 | * undefined, the default render state is used.
52 | *
53 | * @type {RenderState}
54 | *
55 | * @default undefined
56 | *
57 | * @see Context#createRenderState
58 | */
59 | var renderState: RenderState?
60 |
61 | /**
62 | * The framebuffer to clear.
63 | *
64 | * @type {Framebuffer}
65 | *
66 | * @default undefined
67 | */
68 | var framebuffer: Framebuffer?
69 |
70 | /**
71 | * The object who created this command. This is useful for debugging command
72 | * execution; it allows you to see who created a command when you only have a
73 | * reference to the command, and can be used to selectively execute commands
74 | * with {@link Scene#debugCommandFilter}.
75 | *
76 | * @type {Object}
77 | *
78 | * @default undefined
79 | *
80 | * @see Scene#debugCommandFilter
81 | */
82 | // FIXME: Owner
83 | weak var owner: AnyObject? = nil
84 |
85 | var debugOverlappingFrustums: Int = 0
86 | var executeInClosestFrustum: Bool = false
87 |
88 | /**
89 | * Clears color to (0.0, 0.0, 0.0, 0.0); depth to 1.0; and stencil to 0.
90 | *
91 | * @type {ClearCommand}
92 | *
93 | * @constant
94 | */
95 | init (color: Cartesian4? = nil, depth: Double? = nil, stencil: UInt32? = nil, renderState: RenderState? = nil, framebuffer: Framebuffer? = nil, owner: AnyObject? = nil) {
96 |
97 | self.color = color
98 | self.depth = depth
99 | self.stencil = stencil
100 | self.renderState = renderState
101 | self.framebuffer = framebuffer
102 | self.owner = owner
103 | }
104 |
105 | static func all() -> ClearCommand {
106 | return ClearCommand(color: Cartesian4(), depth: 1.0, stencil: 1, renderState: nil)
107 | }
108 |
109 | func execute(_ context: Context, passState: PassState?) {
110 | context.clear(self, passState: passState)
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/CesiumKit/Platform/ImageExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extensions.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 4/10/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | #if os(OSX)
12 | import AppKit.NSImage
13 |
14 | extension NSImage {
15 | var cgImage: CGImage? {
16 | get {
17 | guard let imageData = tiffRepresentation else {
18 | return nil
19 | }
20 | guard let source = CGImageSourceCreateWithData(imageData as CFData, nil) else {
21 | return nil
22 | }
23 | let maskRef = CGImageSourceCreateImageAtIndex(source, 0, nil)
24 | return maskRef
25 | }
26 | }
27 | }
28 | #elseif os(iOS)
29 | import UIKit.UIImage
30 | #endif
31 |
32 | extension CGImage {
33 | class func loadFromURL (_ url: String, completionBlock: @escaping (CGImage?, NSError?) -> ()) {
34 |
35 | let imageOperation = NetworkOperation(url: url)
36 | imageOperation.completionBlock = {
37 | if let error = imageOperation.error {
38 | completionBlock(nil, error)
39 | }
40 | completionBlock(CGImage.from(imageOperation.data), nil)
41 | }
42 | imageOperation.enqueue()
43 | }
44 |
45 | class func from(_ data: Data) -> CGImage? {
46 | #if os(OSX)
47 | let nsImage = NSImage(data: data)
48 | return nsImage?.cgImage
49 | #elseif os(iOS)
50 | let uiImage = UIImage(data: data)
51 | return uiImage?.cgImage
52 | #endif
53 | }
54 |
55 | func renderToPixelArray (colorSpace cs: CGColorSpace, premultiplyAlpha: Bool, flipY: Bool) -> (array: [UInt8], bytesPerRow: Int)? {
56 |
57 | let width = self.width
58 | let height = self.height
59 | let bitsPerComponent = self.bitsPerComponent
60 | let numberOfComponents = 4
61 |
62 | let bytesPerPixel = (bitsPerComponent * numberOfComponents + 7)/8
63 |
64 | let bytesPerRow = bytesPerPixel * width
65 |
66 | let alphaInfo: CGImageAlphaInfo
67 | if bytesPerPixel == 1 {
68 | // no alpha info in single byte pixel array
69 | alphaInfo = .none
70 | } else if premultiplyAlpha {
71 | alphaInfo = .premultipliedLast
72 | } else {
73 | alphaInfo = .last
74 | }
75 |
76 | let bitmapInfo: CGBitmapInfo = [CGBitmapInfo(rawValue: alphaInfo.rawValue)]
77 |
78 | let pixelBuffer = [UInt8](repeating: 0, count: bytesPerRow * height) // if 4 components per pixel (RGBA)
79 |
80 | guard let bitmapContext = CGContext(data: UnsafeMutableRawPointer(mutating: pixelBuffer), width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: cs, bitmapInfo: bitmapInfo.rawValue) else {
81 | assertionFailure("bitmapContext == nil")
82 | return nil
83 | }
84 |
85 | let imageRect = CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height))
86 |
87 | if flipY {
88 | let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(height))
89 | bitmapContext.concatenate(flipVertical)
90 | }
91 | bitmapContext.draw(self, in: imageRect)
92 | return (pixelBuffer, bytesPerRow)
93 | }
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/CesiumKit/Core/GeographicProjection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GeographicProjection.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 11/06/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | * A simple map projection where longitude and latitude are linearly mapped to X and Y by multiplying
13 | * them by the {@link Ellipsoid#maximumRadius}. This projection
14 | * is commonly known as geographic, equirectangular, equidistant cylindrical, or plate carrée. It
15 | * is also known as EPSG:4326.
16 | *
17 | * @alias GeographicProjection
18 | * @constructor
19 | * @immutable
20 | *
21 | * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid.
22 | *
23 | * @see WebMercatorProjection
24 | */
25 | public struct GeographicProjection: MapProjection {
26 |
27 | public let ellipsoid: Ellipsoid
28 | public let semimajorAxis: Double
29 | public let oneOverSemimajorAxis: Double
30 |
31 | public init (ellipsoid: Ellipsoid = Ellipsoid.wgs84) {
32 | self.ellipsoid = ellipsoid
33 | semimajorAxis = ellipsoid.maximumRadius
34 | oneOverSemimajorAxis = 1.0 / semimajorAxis
35 | }
36 |
37 | /**
38 | * Projects a set of {@link Cartographic} coordinates, in radians, to map coordinates, in meters.
39 | * X and Y are the longitude and latitude, respectively, multiplied by the maximum radius of the
40 | * ellipsoid. Z is the unmodified height.
41 | *
42 | * @param {Cartographic} cartographic The coordinates to project.
43 | * @param {Cartesian3} [result] An instance into which to copy the result. If this parameter is
44 | * undefined, a new instance is created and returned.
45 | * @returns {Cartesian3} The projected coordinates. If the result parameter is not undefined, the
46 | * coordinates are copied there and that instance is returned. Otherwise, a new instance is
47 | * created and returned.
48 | */
49 | public func project(_ cartographic: Cartographic) -> Cartesian3 {
50 | // Actually this is the special case of equidistant cylindrical called the plate carree
51 | return Cartesian3(x: cartographic.longitude * semimajorAxis,
52 | y: cartographic.latitude * semimajorAxis,
53 | z: cartographic.height)
54 | }
55 |
56 | /**
57 | * Unprojects a set of projected {@link Cartesian3} coordinates, in meters, to {@link Cartographic}
58 | * coordinates, in radians. Longitude and Latitude are the X and Y coordinates, respectively,
59 | * divided by the maximum radius of the ellipsoid. Height is the unmodified Z coordinate.
60 | *
61 | * @param {Cartesian3} cartesian The Cartesian position to unproject with height (z) in meters.
62 | * @param {Cartographic} [result] An instance into which to copy the result. If this parameter is
63 | * undefined, a new instance is created and returned.
64 | * @returns {Cartographic} The unprojected coordinates. If the result parameter is not undefined, the
65 | * coordinates are copied there and that instance is returned. Otherwise, a new instance is
66 | * created and returned.
67 | */
68 | public func unproject(_ cartesian: Cartesian3) -> Cartographic {
69 | let longitude = cartesian.x * oneOverSemimajorAxis
70 | let latitude = cartesian.y * oneOverSemimajorAxis
71 | let height = cartesian.z
72 | return Cartographic(longitude: longitude, latitude: latitude, height: height)
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/CesiumKit/Core/MergeSort.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MergeSort.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 8/11/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class MergeSort {
12 | /*
13 | var leftScratchArray = [];
14 | var rightScratchArray = [];
15 |
16 | function merge(array, compare, userDefinedObject, start, middle, end) {
17 | var leftLength = middle - start + 1;
18 | var rightLength = end - middle;
19 |
20 | var left = leftScratchArray;
21 | var right = rightScratchArray;
22 |
23 | var i;
24 | var j;
25 |
26 | for (i = 0; i < leftLength; ++i) {
27 | left[i] = array[start + i];
28 | }
29 |
30 | for (j = 0; j < rightLength; ++j) {
31 | right[j] = array[middle + j + 1];
32 | }
33 |
34 | i = 0;
35 | j = 0;
36 | for (var k = start; k <= end; ++k) {
37 | var leftElement = left[i];
38 | var rightElement = right[j];
39 | if (i < leftLength && (j >= rightLength || compare(leftElement, rightElement, userDefinedObject) <= 0)) {
40 | array[k] = leftElement;
41 | ++i;
42 | } else if (j < rightLength) {
43 | array[k] = rightElement;
44 | ++j;
45 | }
46 | }
47 | }
48 |
49 | function sort(array, compare, userDefinedObject, start, end) {
50 | if (start >= end) {
51 | return;
52 | }
53 |
54 | var middle = Math.floor((start + end) * 0.5);
55 | sort(array, compare, userDefinedObject, start, middle);
56 | sort(array, compare, userDefinedObject, middle + 1, end);
57 | merge(array, compare, userDefinedObject, start, middle, end);
58 | }
59 |
60 | /**
61 | * A stable merge sort.
62 | *
63 | * @exports mergeSort
64 | *
65 | * @param {Array} array The array to sort.
66 | * @param {mergeSort~Comparator} comparator The function to use to compare elements in the array.
67 | * @param {Object} [userDefinedObject] An object to pass as the third parameter to comparator.
68 | *
69 | * @example
70 | * // Assume array contains BoundingSpheres in world coordinates.
71 | * // Sort them in ascending order of distance from the camera.
72 | * var position = camera.positionWC;
73 | * Cesium.mergeSort(array, function(a, b, position) {
74 | * return Cesium.BoundingSphere.distanceSquaredTo(b, position) - Cesium.BoundingSphere.distanceSquaredTo(a, position);
75 | * }, position);
76 | */
77 | var mergeSort = function(array, comparator, userDefinedObject) {
78 | //>>includeStart('debug', pragmas.debug);
79 | if (!defined(array)) {
80 | throw new DeveloperError('array is required.');
81 | }
82 | if (!defined(comparator)) {
83 | throw new DeveloperError('comparator is required.');
84 | }
85 | //>>includeEnd('debug');
86 |
87 | var length = array.length;
88 | var scratchLength = Math.ceil(length * 0.5);
89 |
90 | // preallocate space in scratch arrays
91 | leftScratchArray.length = scratchLength;
92 | rightScratchArray.length = scratchLength;
93 |
94 | sort(array, comparator, userDefinedObject, 0, length - 1);
95 |
96 | // trim scratch arrays
97 | leftScratchArray.length = 0;
98 | rightScratchArray.length = 0;
99 | };
100 |
101 | /**
102 | * A function used to compare two items while performing a merge sort.
103 | * @callback mergeSort~Comparator
104 | *
105 | * @param {Object} a An item in the array.
106 | * @param {Object} b An item in the array.
107 | * @param {Object} [userDefinedObject] An object that was passed to {@link mergeSort}.
108 | * @returns {Number} Returns a negative value if a is less than b,
109 | * a positive value if a is greater than b, or
110 | * 0 if a is equal to b.
111 | *
112 | * @example
113 | * function compareNumbers(a, b, userDefinedObject) {
114 | * return a - b;
115 | * }
116 | */
117 |
118 | return mergeSort;
119 | });
120 | */
121 | }
--------------------------------------------------------------------------------
/CesiumKitRunner/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/CesiumKitRunner OSX/CesiumViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // CesiumKitRunner OSX
4 | //
5 | // Created by Ryan Walklin on 1/08/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import MetalKit
11 | import CesiumKit
12 |
13 | class CesiumViewController: NSViewController {
14 |
15 | fileprivate var _cesiumKitController: CesiumKitController! = nil
16 |
17 | @IBOutlet var _metalView: MTKView!
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 |
22 | view.layer!.contentsScale = NSScreen.main()?.backingScaleFactor ?? 1.0
23 | _cesiumKitController = CesiumKitController(view: _metalView)
24 | _metalView.delegate = _cesiumKitController
25 | _cesiumKitController.startRendering()
26 | }
27 |
28 | override func viewWillAppear() {
29 | _metalView.window?.acceptsMouseMovedEvents = true
30 | }
31 |
32 | override func mouseDown(with event: NSEvent) {
33 | let locationInWindow = event.locationInWindow
34 | let localPoint = _metalView.convert(locationInWindow, from: nil)
35 |
36 | let viewHeight = Double(_metalView.bounds.height)
37 | let position = Cartesian2(x: Double(localPoint.x), y: viewHeight - Double(localPoint.y))
38 |
39 | let modifier: KeyboardEventModifier?
40 | if event.modifierFlags.contains(.control) {
41 | modifier = .ctrl
42 | } else if event.modifierFlags.contains(.option) {
43 | modifier = .alt
44 | } else if event.modifierFlags.contains(.shift) {
45 | modifier = .shift
46 | } else {
47 | modifier = nil
48 | }
49 | _cesiumKitController.handleMouseDown(.left, position: position, modifier: modifier)
50 | }
51 |
52 | override func mouseDragged(with event: NSEvent) {
53 | let locationInWindow = event.locationInWindow
54 | let localPoint = _metalView.convert(locationInWindow, from: nil)
55 | let viewHeight = Double(_metalView.bounds.height)
56 | let position = Cartesian2(x: Double(localPoint.x), y: viewHeight - Double(localPoint.y))
57 |
58 | let modifier: KeyboardEventModifier?
59 | if event.modifierFlags.contains(.control) {
60 | modifier = .ctrl
61 | } else if event.modifierFlags.contains(.option) {
62 | modifier = .alt
63 | } else if event.modifierFlags.contains(.shift) {
64 | modifier = .shift
65 | } else {
66 | modifier = nil
67 | }
68 | _cesiumKitController.handleMouseMove(.left, position: position, modifier: modifier)
69 | }
70 |
71 | override func mouseMoved(with event: NSEvent) {
72 |
73 | }
74 |
75 | override func mouseUp(with event: NSEvent) {
76 | let locationInWindow = event.locationInWindow
77 | let localPoint = _metalView.convert(locationInWindow, from: nil)
78 | let viewHeight = Double(_metalView.bounds.height)
79 | let position = Cartesian2(x: Double(localPoint.x), y: viewHeight - Double(localPoint.y))
80 |
81 | let modifier: KeyboardEventModifier?
82 | if event.modifierFlags.contains(.control) {
83 | modifier = .ctrl
84 | } else if event.modifierFlags.contains(.option) {
85 | modifier = .alt
86 | } else if event.modifierFlags.contains(.shift) {
87 | modifier = .shift
88 | } else {
89 | modifier = nil
90 | }
91 | _cesiumKitController.handleMouseUp(.left, position: position, modifier: modifier)
92 | }
93 |
94 | override func scrollWheel(with event: NSEvent) {
95 | _cesiumKitController.handleWheel(Double(event.deltaX), deltaY: Double(event.deltaY))
96 | }
97 |
98 |
99 | }
100 |
101 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/Framebuffer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Framebuffer.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 15/06/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | import MetalKit
10 |
11 | /**
12 | * @private
13 | */
14 | class Framebuffer {
15 |
16 | let maximumColorAttachments: Int
17 |
18 | fileprivate (set) var colorTextures: [Texture]?
19 |
20 | fileprivate (set) var depthTexture: Texture?
21 |
22 | fileprivate (set) var stencilTexture: Texture?
23 |
24 | var depthStencilTexture: Texture? {
25 | return depthTexture === stencilTexture ? depthTexture : nil
26 | }
27 |
28 | var renderPassDescriptor: MTLRenderPassDescriptor {
29 | return _rpd
30 | }
31 |
32 | fileprivate var _rpd = MTLRenderPassDescriptor()
33 |
34 | var numberOfColorAttachments: Int {
35 | return colorTextures?.count ?? 0
36 | }
37 |
38 | /**
39 | * True if the framebuffer has a depth attachment. Depth attachments include
40 | * depth and depth-stencil textures, and depth and depth-stencil renderbuffers. When
41 | * rendering to a framebuffer, a depth attachment is required for the depth test to have effect.
42 | * @memberof Framebuffer.prototype
43 | * @type {Boolean}
44 | */
45 | var hasDepthAttachment: Bool {
46 | return depthTexture != nil
47 | }
48 |
49 | init (
50 | maximumColorAttachments: Int,
51 | colorTextures: [Texture]? = nil,
52 | depthTexture: Texture? = nil,
53 | stencilTexture: Texture? = nil) {
54 | self.maximumColorAttachments = maximumColorAttachments
55 | self.colorTextures = colorTextures
56 | self.depthTexture = depthTexture
57 | self.stencilTexture = stencilTexture
58 |
59 | assert(colorTextures == nil || colorTextures!.count <= Int(maximumColorAttachments), "The number of color attachments exceeds the number supported.")
60 | updateRenderPassDescriptor()
61 | }
62 |
63 | func updateFromDrawable (context: Context, drawable: CAMetalDrawable, depthStencil: MTLTexture?) {
64 |
65 | colorTextures = [Texture(context: context, metalTexture: drawable.texture)]
66 | depthTexture = depthStencil == nil ? nil : Texture(context: context, metalTexture: depthStencil!)
67 | stencilTexture = depthTexture
68 |
69 | updateRenderPassDescriptor()
70 | }
71 |
72 | func update (colorTextures: [Texture]?, depthTexture: Texture?, stencilTexture: Texture?) {
73 | self.colorTextures = colorTextures
74 | self.depthTexture = depthTexture
75 | self.stencilTexture = stencilTexture
76 | updateRenderPassDescriptor()
77 | }
78 |
79 | fileprivate func updateRenderPassDescriptor () {
80 | if let colorTextures = self.colorTextures {
81 | for (i, colorTexture) in colorTextures.enumerated() {
82 | _rpd.colorAttachments[i].texture = colorTexture.metalTexture
83 | _rpd.colorAttachments[i].storeAction = .store
84 | }
85 | } else {
86 | for i in 0.. Self
14 | func -(lhs: Self, rhs: Self) -> Self
15 | func *(lhs: Self, rhs: Self) -> Self
16 | func /(lhs: Self, rhs: Self) -> Self
17 | func *(lhs: Self, rhs: Double) -> Self
18 | prefix func -(cartesian: Self) -> Self
19 |
20 | func dot(other: Self) -> Double
21 | func multiplyComponents(other: Self) -> Self
22 |
23 | func multiplyByScalar(scalar: Double) -> Self
24 | func divideByScalar(scalar: Double) -> Self
25 |
26 | func add(other: Self) -> Self
27 | func subtract(other: Self) -> Self
28 |
29 | func negate() -> Self
30 | }
31 |
32 | extension CartesianType {
33 |
34 | /**
35 | * Computes the componentwise product of two Cartesians.
36 | *
37 | * @param {Cartesian3} left The first Cartesian.
38 | * @param {Cartesian3} right The second Cartesian.
39 | * @param {Cartesian3} [result] The object onto which to store the result.
40 | * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
41 | */
42 | func multiplyComponents(other: Self) -> Self {
43 | return self * other
44 | }
45 |
46 | /**
47 | * Multiplies the provided Cartesian componentwise by the provided scalar.
48 | *
49 | * @param {Cartesian3} cartesian The Cartesian to be scaled.
50 | * @param {Number} scalar The scalar to multiply with.
51 | * @param {Cartesian3} [result] The object onto which to store the result.
52 | * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
53 | */
54 | func multiplyByScalar(scalar: Double) -> Self {
55 | return self * scalar
56 | }
57 |
58 | /**
59 | * Divides the provided Cartesian componentwise by the provided scalar.
60 | *
61 | * @param {Cartesian3} cartesian The Cartesian to be divided.
62 | * @param {Number} scalar The scalar to divide by.
63 | * @param {Cartesian3} [result] The object onto which to store the result.
64 | * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
65 | */
66 | func divideByScalar(scalar: Double) -> Self {
67 | return multiplyByScalar(1.0/scalar)
68 | }
69 |
70 | /**
71 | * Computes the componentwise sum of two Cartesians.
72 | *
73 | * @param {Cartesian3} left The first Cartesian.
74 | * @param {Cartesian3} right The second Cartesian.
75 | * @param {Cartesian3} [result] The object onto which to store the result.
76 | * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
77 | */
78 | func add(other: Self) -> Self {
79 | return self + other
80 | }
81 |
82 | /**
83 | * Computes the componentwise difference of two Cartesians.
84 | *
85 | * @param {Cartesian3} left The first Cartesian.
86 | * @param {Cartesian3} right The second Cartesian.
87 | * @param {Cartesian3} [result] The object onto which to store the result.
88 | * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
89 | */
90 | func subtract(other: Self) -> Self {
91 | return self - other
92 | }
93 |
94 | /**
95 | * Negates the provided Cartesian.
96 | *
97 | * @param {Cartesian3} cartesian The Cartesian to be negated.
98 | * @param {Cartesian3} [result] The object onto which to store the result.
99 | * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
100 | */
101 | func negate() -> Self {
102 | return -self
103 | }
104 |
105 |
106 | }
--------------------------------------------------------------------------------
/CesiumKit/Scene/ImageryLayerFeatureInfo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageryLayerFeatureInfo.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 31/10/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | * Describes a rasterized feature, such as a point, polygon, polyline, etc., in an imagery layer.
13 | *
14 | * @alias ImageryLayerFeatureInfo
15 | * @constructor
16 | */
17 | public struct ImageryLayerFeatureInfo {
18 |
19 | /**
20 | * Gets or sets the name of the feature.
21 | * @type {String}
22 | */
23 | var name: String
24 |
25 | /**
26 | * Gets or sets an HTML description of the feature. The HTML is not trusted and should
27 | * be sanitized before display to the user.
28 | * @type {String}
29 | */
30 | var description: String
31 |
32 | /**
33 | * Gets or sets the position of the feature, or undefined if the position is not known.
34 | *
35 | * @type {Cartographic}
36 | */
37 | var position: Cartographic
38 |
39 | /**
40 | * Gets or sets the raw data describing the feature. The raw data may be in any
41 | * number of formats, such as GeoJSON, KML, etc.
42 | * @type {Object}
43 | */
44 | var data: Data
45 |
46 | /**
47 | * Configures the name of this feature by selecting an appropriate property. The name will be obtained from
48 | * one of the following sources, in this order: 1) the property with the name 'name', 2) the property with the name 'title',
49 | * 3) the first property containing the word 'name', 4) the first property containing the word 'title'. If
50 | * the name cannot be obtained from any of these sources, the existing name will be left unchanged.
51 | *
52 | * @param {Object} properties An object literal containing the properties of the feature.
53 | */
54 | func configureNameFromProperties (_ properties: [String]) {
55 | /*
56 | var namePropertyPrecedence = 10;
57 | var nameProperty;
58 |
59 | for (var key in properties) {
60 | if (properties.hasOwnProperty(key) && properties[key]) {
61 | var lowerKey = key.toLowerCase();
62 |
63 | if (namePropertyPrecedence > 1 && lowerKey === 'name') {
64 | namePropertyPrecedence = 1;
65 | nameProperty = key;
66 | } else if (namePropertyPrecedence > 2 && lowerKey === 'title') {
67 | namePropertyPrecedence = 2;
68 | nameProperty = key;
69 | } else if (namePropertyPrecedence > 3 && /name/i.test(key)) {
70 | namePropertyPrecedence = 3;
71 | nameProperty = key;
72 | } else if (namePropertyPrecedence > 4 && /title/i.test(key)) {
73 | namePropertyPrecedence = 4;
74 | nameProperty = key;
75 | }
76 | }
77 | }
78 |
79 | if (defined(nameProperty)) {
80 | this.name = properties[nameProperty];
81 | }*/
82 | }
83 |
84 | /**
85 | * Configures the description of this feature by creating an HTML table of properties and their values.
86 | *
87 | * @param {Object} properties An object literal containing the properties of the feature.
88 | */
89 | func configureDescriptionFromProperties (_ properties: [String]) {
90 | /*function describe(properties) {
91 | var html = '';
92 | for (var key in properties) {
93 | if (properties.hasOwnProperty(key)) {
94 | var value = properties[key];
95 | if (defined(value)) {
96 | if (typeof value === 'object') {
97 | html += '' + key + ' ' + describe(value) + ' ';
98 | } else {
99 | html += '' + key + ' ' + value + ' ';
100 | }
101 | }
102 | }
103 | }
104 | html += '
';
105 |
106 | return html;
107 | }
108 |
109 | this.description = describe(properties);*/
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/CesiumKit/Platform/Data+ArrayView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+ArrayView.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 26/12/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Data {
12 |
13 | public func getFloat32(_ pos: Int, littleEndian: Bool = true) -> Float {
14 | assert(self.count >= pos + MemoryLayout.size, "pos out of bounds")
15 | var result: Float = 0.0
16 | _ = withUnsafeBytes { pointer in
17 | memcpy(&result, pointer+pos, MemoryLayout.size(ofValue: result))
18 | }
19 | return result
20 | }
21 |
22 | public func getFloat64(_ pos: Int, littleEndian: Bool = true) -> Double {
23 | assert(self.count >= pos + MemoryLayout.size, "pos out of bounds")
24 | var result: Double = 0.0
25 | Float()
26 | _ = withUnsafeBytes { pointer in
27 | memcpy(&result, pointer+pos, MemoryLayout.size(ofValue: result))
28 | }
29 | return result
30 | }
31 |
32 | public func getUInt8(_ pos: Int) -> UInt8 {
33 | assert(self.count >= pos + MemoryLayout.size, "pos out of bounds")
34 | var result: UInt8 = 0
35 | _ = withUnsafeBytes { pointer in
36 | memcpy(&result, pointer+pos, MemoryLayout.size(ofValue: result))
37 | }
38 | return result
39 | }
40 |
41 | public func getUInt16(_ pos: Int, littleEndian: Bool = true) -> UInt16 {
42 | assert(self.count >= pos + MemoryLayout.size, "pos out of bounds")
43 | var result: UInt16 = 0
44 | _ = withUnsafeBytes { pointer in
45 | memcpy(&result, pointer+pos, MemoryLayout.size(ofValue: result))
46 | }
47 | return littleEndian ? result : result.bigEndian
48 | }
49 |
50 | public func getUInt32(_ pos: Int, littleEndian: Bool = true) -> UInt32 {
51 | assert(self.count >= pos + MemoryLayout.size, "pos out of bounds")
52 | var result: UInt32 = 0
53 | _ = withUnsafeBytes { pointer in
54 | memcpy(&result, pointer+pos, MemoryLayout.size(ofValue: result))
55 | }
56 | return littleEndian ? result : result.bigEndian
57 | }
58 |
59 | public func getUInt8Array(_ pos: Int = 0, elementCount: Int? = nil) -> [UInt8] {
60 | let elementCount = elementCount ?? self.count
61 | assert(self.count >= pos + elementCount, "requested array out of bounds")
62 | var result = [UInt8](repeating: 0, count: elementCount)
63 | copyBytes(to: &result, from: Range(uncheckedBounds: (lower: pos, upper: pos+elementCount)))
64 | return result
65 | }
66 |
67 | public func getUInt16Array(_ pos: Int = 0, elementCount: Int? = nil, littleEndian: Bool = true) -> [UInt16] {
68 | let elementCount = elementCount ?? self.count / MemoryLayout.stride
69 | let arrayByteLength = elementCount * MemoryLayout.stride
70 | assert(self.count >= pos + arrayByteLength, "requested array out of bounds")
71 | var result = [UInt16](repeating: 0, count: elementCount)
72 | _ = result.withUnsafeMutableBufferPointer { (pointer: inout UnsafeMutableBufferPointer) in
73 | memcpy(pointer.baseAddress, (self as NSData).bytes + pos, arrayByteLength)
74 | }
75 | return littleEndian ? result : result.map { $0.bigEndian }
76 | }
77 |
78 | public func getUInt32Array(_ pos: Int = 0, elementCount: Int? = nil, littleEndian: Bool = true) -> [UInt32] {
79 | let elementCount = elementCount ?? self.count / MemoryLayout.stride
80 | let arrayByteLength = elementCount * MemoryLayout.stride
81 | assert(self.count >= pos + arrayByteLength, "requested array out of bounds")
82 | var result = [UInt32](repeating: 0, count: elementCount)
83 | _ = result.withUnsafeMutableBufferPointer { (pointer: inout UnsafeMutableBufferPointer) in
84 | memcpy(pointer.baseAddress, (self as NSData).bytes + pos, arrayByteLength)
85 | }
86 | return littleEndian ? result : result.map { $0.bigEndian }
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/ComputeCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComputeCommand.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 10/10/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | * Represents a command to the renderer for GPU Compute (using old-school GPGPU).
13 | *
14 | * @private
15 | */
16 | class ComputeCommand: Command {
17 |
18 | /**
19 | * The vertex array. If none is provided, a viewport quad will be used.
20 | *
21 | * @type {VertexArray}
22 | * @default undefined
23 | */
24 | var vertexArray: VertexArray?
25 |
26 | /**
27 | * The fragment shader source. The default vertex shader is ViewportQuadVS.
28 | *
29 | * @type {ShaderSource}
30 | * @default undefined
31 | */
32 | var fragmentShaderSource: ShaderSource?
33 |
34 | /**
35 | * The shader program to apply.
36 | *
37 | * @type {ShaderProgram}
38 | * @default undefined
39 | */
40 | var pipeline: RenderPipeline?
41 |
42 | /**
43 | * An object with functions whose names match the uniforms in the shader program
44 | * and return values to set those uniforms.
45 | *
46 | * @type {Object}
47 | * @default undefined
48 | */
49 | var uniformMap: UniformMap?
50 |
51 | /**
52 | * Texture to use for offscreen rendering.
53 | *
54 | * @type {Texture}
55 | * @default undefined
56 | */
57 | var outputTexture: Texture?
58 |
59 | /**
60 | * Function that is called immediately before the ComputeCommand is executed. Used to
61 | * update any renderer resources. Takes the ComputeCommand as its single argument.
62 | *
63 | * @type {Function}
64 | * @default undefined
65 | */
66 | var preExecute: ((ComputeCommand) -> ())?
67 |
68 | /**
69 | * Function that is called after the ComputeCommand is executed. Takes the output
70 | * texture as its single argument.
71 | *
72 | * @type {Function}
73 | * @default undefined
74 | */
75 | var postExecute: ((Texture) -> ())?
76 |
77 | /**
78 | * Whether the renderer resources will persist beyond this call. If not, they
79 | * will be destroyed after completion.
80 | *
81 | * @type {Boolean}
82 | * @default false
83 | */
84 | var persists: Bool
85 |
86 | /**
87 | * The pass when to render. Always compute pass.
88 | *
89 | * @type {Pass}
90 | * @default Pass.COMPUTE;
91 | */
92 | let pass: Pass = .compute
93 |
94 | /**
95 | * The object who created this command. This is useful for debugging command
96 | * execution; it allows us to see who created a command when we only have a
97 | * reference to the command, and can be used to selectively execute commands
98 | * with {@link Scene#debugCommandFilter}.
99 | *
100 | * @type {Object}
101 | * @default undefined
102 | *
103 | * @see Scene#debugCommandFilter
104 | */
105 | var owner: AnyObject? = nil
106 |
107 | init(
108 | vertexArray: VertexArray? = nil,
109 | fragmentShaderSource: ShaderSource? = nil,
110 | renderPipeline: RenderPipeline? = nil,
111 | uniformMap: UniformMap? = nil,
112 | outputTexture: Texture? = nil,
113 | preExecute: ((ComputeCommand) -> ())? = nil,
114 | postExecute: ((Texture) -> ())? = nil,
115 | persists: Bool = false,
116 | owner: AnyObject? = nil) {
117 | self.vertexArray = vertexArray
118 | self.fragmentShaderSource = fragmentShaderSource
119 | self.pipeline = renderPipeline
120 | self.uniformMap = uniformMap
121 | self.outputTexture = outputTexture
122 | self.preExecute = preExecute
123 | self.postExecute = postExecute
124 | self.persists = persists
125 | self.owner = owner
126 | }
127 |
128 | /**
129 | * Executes the compute command.
130 | *
131 | * @param {Context} context The context that processes the compute command.
132 | */
133 | func execute (_ computeEngine: ComputeEngine) {
134 | computeEngine.execute(self)
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/TileReplacementQueue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TileReplacementQueue.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 28/09/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 |
10 | /**
11 | * A priority queue of tiles to be replaced, if necessary, to make room for new tiles. The queue
12 | * is implemented as a linked list.
13 | *
14 | * @alias TileReplacementQueue
15 | * @private
16 | */
17 | class TileReplacementQueue {
18 |
19 | var head: QuadtreeTile? = nil
20 |
21 | var tail: QuadtreeTile? = nil
22 |
23 | var count = 0
24 |
25 | fileprivate var _lastBeforeStartOfFrame: QuadtreeTile? = nil
26 |
27 | fileprivate var _tileProvider: GlobeSurfaceTileProvider
28 |
29 | init (tileProvider: GlobeSurfaceTileProvider) {
30 | _tileProvider = tileProvider
31 | }
32 |
33 | /**
34 | * Marks the start of the render frame. Tiles before (closer to the head) this tile in the
35 | * list were used last frame and must not be unloaded.
36 | */
37 | func markStartOfRenderFrame() {
38 | _lastBeforeStartOfFrame = head
39 | }
40 |
41 | /**
42 | * Reduces the size of the queue to a specified size by unloading the least-recently used
43 | * tiles. Tiles that were used last frame will not be unloaded, even if that puts the number
44 | * of tiles above the specified maximum.
45 | *
46 | * @param {Number} maximumTiles The maximum number of tiles in the queue.
47 | */
48 | func trimTiles(_ maximumTiles: Int) {
49 | var tileToTrim = tail
50 | var keepTrimming = true
51 | while keepTrimming && _lastBeforeStartOfFrame != nil && count > maximumTiles && tileToTrim != nil {
52 | // Stop trimming after we process the last tile not used in the
53 | // current frame.
54 | keepTrimming = tileToTrim! != _lastBeforeStartOfFrame
55 |
56 | let previous = tileToTrim!.replacementPrevious
57 |
58 | if tileToTrim!.eligibleForUnloading {
59 | tileToTrim!.freeResources(_tileProvider)
60 | remove(tileToTrim!)
61 | }
62 | tileToTrim = previous
63 | }
64 | }
65 |
66 | func remove(_ item: QuadtreeTile) {
67 | let previous = item.replacementPrevious
68 | let next = item.replacementNext
69 |
70 | if item == _lastBeforeStartOfFrame {
71 | _lastBeforeStartOfFrame = next
72 | }
73 |
74 | if (item == head) {
75 | head = next
76 | } else {
77 | previous!.replacementNext = next
78 | }
79 |
80 | if (item == tail) {
81 | tail = previous
82 | } else {
83 | next!.replacementPrevious = previous
84 | }
85 |
86 | item.replacementPrevious = nil
87 | item.replacementNext = nil
88 |
89 | count -= 1
90 | }
91 |
92 | /**
93 | * Marks a tile as rendered this frame and moves it before the first tile that was not rendered
94 | * this frame.
95 | *
96 | * @param {TileReplacementQueue} item The tile that was rendered.
97 | */
98 | func markTileRendered (_ item: QuadtreeTile) {
99 | if head == item {
100 | if (item == _lastBeforeStartOfFrame) {
101 | _lastBeforeStartOfFrame = item.replacementNext
102 | }
103 | return;
104 | }
105 |
106 | count += 1
107 |
108 | if head == nil {
109 | // no other tiles in the list
110 | item.replacementPrevious = nil
111 | item.replacementNext = nil
112 | head = item
113 | tail = item
114 | return
115 | }
116 |
117 | if item.replacementPrevious != nil || item.replacementNext != nil {
118 | // tile already in the list, remove from its current location
119 | remove(item)
120 | }
121 |
122 | item.replacementPrevious = nil
123 | item.replacementNext = head
124 | head!.replacementPrevious = item
125 |
126 | head = item
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/CesiumKit/Renderer/ComputeEngine.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComputeEngine.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 10/10/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Metal
11 |
12 | class ComputeEngine {
13 |
14 |
15 | /**
16 | * @private
17 | */
18 | let context: Context
19 |
20 | init (context: Context) {
21 | self.context = context
22 | }
23 |
24 | fileprivate func createViewportQuadPipeline(_ fragmentShaderSource: ShaderSource) -> RenderPipeline? {
25 |
26 | let attributes = [
27 | // attribute vec4 position;
28 | VertexAttributes(
29 | buffer: nil,
30 | bufferIndex: VertexDescriptorFirstBufferOffset,
31 | index: 0,
32 | format: .float2,
33 | offset: 0,
34 | size: 8,
35 | normalize: false),
36 | // attribute vec2 textureCoordinates;
37 | VertexAttributes(
38 | buffer: nil,
39 | bufferIndex: VertexDescriptorFirstBufferOffset,
40 | index: 1,
41 | format: .float2,
42 | offset: 8,
43 | size: 8,
44 | normalize: false)
45 | ]
46 |
47 | return RenderPipeline.fromCache(
48 | context: context,
49 | vertexShaderSource: ShaderSource(sources: [Shaders["ViewportQuadVS"]!]),
50 | fragmentShaderSource: fragmentShaderSource,
51 | vertexDescriptor: VertexDescriptor(attributes: attributes),
52 | colorMask: nil,
53 | depthStencil: false)
54 | }
55 |
56 | func execute (_ computeCommand: ComputeCommand) {
57 |
58 | // This may modify the command's resources, so do error checking afterwards
59 | if let preExecute = computeCommand.preExecute {
60 | preExecute(computeCommand)
61 | }
62 |
63 | assert(computeCommand.fragmentShaderSource != nil || computeCommand.pipeline != nil, "computeCommand.fragmentShaderSource or pipeline is required")
64 | guard let outputTexture = computeCommand.outputTexture else {
65 | assertionFailure("computeCommand.outputTexture is required")
66 | return
67 | }
68 |
69 | let framebuffer = Framebuffer(maximumColorAttachments: 1, colorTextures: [computeCommand.outputTexture!], depthTexture: nil, stencilTexture: nil)
70 | let passState = PassState()
71 | passState.context = context
72 | passState.framebuffer = framebuffer
73 |
74 | let vertexArray = computeCommand.vertexArray ?? context.getViewportQuadVertexArray()
75 | let pipeline = computeCommand.pipeline ?? createViewportQuadPipeline(computeCommand.fragmentShaderSource!)
76 | let renderState = RenderState(
77 | device: context.device,
78 | viewport: Cartesian4(x: 0, y: 0, width: Double(outputTexture.width), height: Double(outputTexture.height)))
79 |
80 |
81 | var clearCommand = ClearCommand(color: Cartesian4(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0))
82 | clearCommand.renderState = renderState
83 | clearCommand.execute(context, passState: passState)
84 |
85 | let drawCommand = DrawCommand()
86 | drawCommand.vertexArray = vertexArray
87 | drawCommand.renderState = renderState
88 | drawCommand.pipeline = pipeline
89 | drawCommand.uniformMap = computeCommand.uniformMap
90 | if let map = drawCommand.uniformMap {
91 | map.uniformBufferProvider = drawCommand.pipeline!.shaderProgram.createUniformBufferProvider(context.device, deallocationBlock: nil)
92 | }
93 |
94 | guard let renderPass = context.createRenderPass(passState) else {
95 | logPrint(.critical, "Cannot create renderPass")
96 | return
97 | }
98 | drawCommand.execute(context, renderPass: renderPass)
99 | renderPass.complete()
100 | //FIXME: postExecute
101 | if let postExecute = computeCommand.postExecute {
102 | postExecute(computeCommand.outputTexture!)
103 | }
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/OffscreenQuadPrimitive.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OffscreenQuadPrimitive
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 12/03/2016.
6 | // Copyright © 2016 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /** A render-to-texture primitive allowing multiple draw commands.
12 | Most useful for creating HUDs and other UI.
13 | */
14 | open class OffscreenQuadPrimitive: Primitive {
15 |
16 | let height, width: Int
17 |
18 | fileprivate weak var _context: Context!
19 |
20 | fileprivate var _text = [TextRenderer]()
21 |
22 | fileprivate var _textCommands = [DrawCommand]()
23 |
24 | fileprivate var _rectangles = [DrawCommand]()
25 |
26 | fileprivate let _passState: PassState
27 |
28 | fileprivate let _clearCommand = ClearCommand(
29 | color: Color(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0)
30 | )
31 |
32 | init (context: Context, width: Int, height: Int) {
33 | _context = context
34 | self.width = width
35 | self.height = height
36 |
37 | let options = TextureOptions(
38 | width: width,
39 | height: height,
40 | premultiplyAlpha: false,
41 | usage: [.ShaderRead, .RenderTarget])
42 |
43 | let texture = Texture(context: context, options: options)
44 |
45 | let framebuffer = Framebuffer(
46 | maximumColorAttachments: context.limits.maximumColorAttachments,
47 | colorTextures: [texture]
48 | )
49 | _passState = PassState()
50 | _passState.context = context
51 | _passState.framebuffer = framebuffer
52 | }
53 |
54 | open func addString (_ string: String, fontName: String, color: Color, pointSize: Int, rectangle: Cartesian4) -> Int {
55 | let text = TextRenderer(string: string, fontName: fontName, color: color, pointSize: pointSize, viewportRect: rectangle, offscreenTarget: true)
56 | _text.append(text)
57 | return _text.count-1
58 | }
59 |
60 | open func updateString (_ index: Int, newText: String) {
61 |
62 | }
63 |
64 | open func addRectangle (_ bounds: Cartesian4, material: Material) -> Int {
65 |
66 | let rs = RenderState(
67 | device: _context.device,
68 | viewport : bounds
69 | )
70 |
71 | let overrides = ViewportQuadOverrides(
72 | renderState: rs,
73 | uniformMap: material.uniformMap,
74 | owner: self
75 | )
76 | let fs = ShaderSource(
77 | sources: [material.shaderSource, Shaders["ViewportQuadFS"]].flatMap { $0 }
78 | )
79 | let command = _context.createViewportQuadCommand(
80 | fragmentShaderSource: fs,
81 | overrides: overrides,
82 | depthStencil: false,
83 | blendingState: nil)
84 |
85 | _rectangles.append(command)
86 |
87 | return _rectangles.count-1
88 | }
89 |
90 |
91 | override func update (_ frameState: inout FrameState) {
92 |
93 | _textCommands.removeAll()
94 |
95 | for text in _text {
96 | text.update(&frameState)
97 | }
98 | }
99 |
100 | /**
101 | * Executes the draw command.
102 | *
103 | * @param {Context} context The renderer context in which to draw.
104 | * @param {RenderPass} [renderPass] The render pass this command is part of.
105 | * @param {RenderState} [renderState] The render state that will override the render state of the command.
106 | * @param {RenderPipeline} [renderPipeline] The render pipeline that will override the shader program of the command.
107 | */
108 | func execute(_ context: Context) {
109 |
110 | guard let renderPass = context.createRenderPass(_passState) else {
111 | return
112 | }
113 | _clearCommand.execute(context, passState: _passState)
114 | for command in _rectangles {
115 | command.execute(context, renderPass: renderPass)
116 | }
117 |
118 | for command in _textCommands {
119 | command.execute(context, renderPass: renderPass)
120 | }
121 | renderPass.complete()
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/BlendingState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BlendingState.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 25/10/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | /**
10 | * The blending state combines {@link BlendEquation} and {@link BlendFunction} and the
11 | * enabled flag to define the full blending state for combining source and
12 | * destination fragments when rendering.
13 | *
14 | * This is a helper when using custom render states with {@link Appearance#renderState}.
15 | *
16 | *
17 | * @namespace
18 | * @alias BlendingState
19 | */
20 | struct BlendingState: Equatable, CustomStringConvertible {
21 | let enabled: Bool
22 | let equationRgb: BlendEquation
23 | let equationAlpha: BlendEquation
24 | let functionSourceRgb: BlendFunction
25 | let functionSourceAlpha: BlendFunction
26 | let functionDestinationRgb: BlendFunction
27 | let functionDestinationAlpha: BlendFunction
28 | let color: Cartesian4?
29 |
30 | /**
31 | * Blending is disabled.
32 | *
33 | * @type {Object}
34 | * @constant
35 | */
36 | static func Disabled() -> BlendingState {
37 | return BlendingState(enabled: false,
38 | equationRgb: .add,
39 | equationAlpha: .add,
40 | functionSourceRgb: .zero,
41 | functionSourceAlpha: .zero,
42 | functionDestinationRgb: .zero,
43 | functionDestinationAlpha: .zero,
44 | color: nil)
45 | }
46 |
47 | /**
48 | * Blending is enabled using alpha blending, source(source.alpha) + destination(1 - source.alpha).
49 | *
50 | * @type {Object}
51 | * @constant
52 | */
53 | static func AlphaBlend() -> BlendingState {
54 | return BlendingState(enabled: true,
55 | equationRgb : .add,
56 | equationAlpha : .add,
57 | functionSourceRgb : .sourceAlpha,
58 | functionSourceAlpha : .sourceAlpha,
59 | functionDestinationRgb : .oneMinusSourceAlpha,
60 | functionDestinationAlpha : .oneMinusSourceAlpha,
61 | color: nil)
62 | }
63 |
64 | static func AlphaBlend(_ color: Cartesian4) -> BlendingState {
65 | return BlendingState(enabled: true,
66 | equationRgb : .add,
67 | equationAlpha : .add,
68 | functionSourceRgb : .sourceAlpha,
69 | functionSourceAlpha : .sourceAlpha,
70 | functionDestinationRgb : .oneMinusSourceAlpha,
71 | functionDestinationAlpha : .oneMinusSourceAlpha,
72 | color: color)
73 | }
74 |
75 | /**
76 | * Blending is enabled using alpha blending with premultiplied alpha, source + destination(1 - source.alpha).
77 | *
78 | * @type {Object}
79 | * @constant
80 | */
81 | static func PremultipliedAlphaBlend(_ color: Cartesian4) -> BlendingState {
82 | return BlendingState(enabled : true,
83 | equationRgb : .add,
84 | equationAlpha : .add,
85 | functionSourceRgb : .one,
86 | functionSourceAlpha : .one,
87 | functionDestinationRgb : .oneMinusSourceAlpha,
88 | functionDestinationAlpha : .oneMinusSourceAlpha,
89 | color: color)
90 | }
91 |
92 | /**
93 | * Blending is enabled using additive blending, source(source.alpha) + destination.
94 | *
95 | * @type {Object}
96 | * @constant
97 | */
98 | static func AdditiveBlend(_ color: Cartesian4) -> BlendingState {
99 | return BlendingState(enabled : true,
100 | equationRgb : .add,
101 | equationAlpha : .add,
102 | functionSourceRgb : .sourceAlpha,
103 | functionSourceAlpha : .sourceAlpha,
104 | functionDestinationRgb : .one,
105 | functionDestinationAlpha : .one,
106 | color: color)
107 | }
108 |
109 | var description: String {
110 | return "r\(equationRgb.rawValue):a\(equationAlpha.rawValue):sr\(functionSourceRgb.rawValue):sa\(functionSourceAlpha.rawValue):dr\(functionDestinationRgb.rawValue):da\(functionDestinationAlpha.rawValue):c\(color?.simdType.debugDescription ?? "nil")"
111 |
112 | }
113 | }
114 |
115 | func == (lhs: BlendingState, rhs: BlendingState) -> Bool {
116 | return lhs.description == rhs.description
117 | }
118 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/TileImagery.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TileImagery.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 16/08/14.
6 | // Copyright (c) 2014 Test Toast. All rights reserved.
7 | //
8 |
9 | /**
10 | * The assocation between a terrain tile and an imagery tile.
11 | *
12 | * @alias TileImagery
13 | * @private
14 | *
15 | * @param {Imagery} imagery The imagery tile.
16 | * @param {Cartesian4} textureCoordinateRectangle The texture rectangle of the tile that is covered
17 | * by the imagery, where X=west, Y=south, Z=east, W=north.
18 | */
19 | class TileImagery {
20 |
21 | var readyImagery: Imagery? = nil
22 |
23 | var loadingImagery: Imagery? = nil
24 |
25 | var textureCoordinateRectangle: Cartesian4? = nil
26 |
27 | var textureTranslationAndScale: Cartesian4? = nil
28 |
29 | init(imagery: Imagery, textureCoordinateRectangle: Cartesian4? = nil) {
30 | loadingImagery = imagery
31 | self.textureCoordinateRectangle = textureCoordinateRectangle
32 | textureTranslationAndScale = nil
33 | }
34 |
35 | /**
36 | * Frees the resources held by this instance.
37 | */
38 | deinit {
39 | if readyImagery != nil {
40 | readyImagery!.releaseReference()
41 | }
42 |
43 | if loadingImagery != nil {
44 | loadingImagery!.releaseReference()
45 | }
46 | }
47 |
48 | /**
49 | * Processes the load state machine for this instance.
50 | *
51 | * @param {Tile} tile The tile to which this instance belongs.
52 | * @param {FrameState} frameState The frameState.
53 | * @returns {Boolean} True if this instance is done loading; otherwise, false.
54 | */
55 | func processStateMachine (_ tile: QuadtreeTile, frameState: inout FrameState) -> Bool {
56 |
57 | let imageryLayer = loadingImagery!.imageryLayer
58 |
59 | loadingImagery!.processStateMachine(frameState: &frameState)
60 |
61 | if loadingImagery!.state == .ready {
62 | if readyImagery != nil {
63 | readyImagery!.releaseReference()
64 | }
65 | readyImagery = loadingImagery
66 | loadingImagery = nil
67 | textureTranslationAndScale = imageryLayer.calculateTextureTranslationAndScale(tile, tileImagery: self)
68 | return true // done loading
69 | }
70 |
71 | // Find some ancestor imagery we can use while this imagery is still loading.
72 | var ancestor = loadingImagery!.parent
73 | var closestAncestorThatNeedsLoading: Imagery?
74 | while ancestor != nil && ancestor!.state != ImageryState.ready {
75 | if ancestor!.state != ImageryState.failed && ancestor!.state != ImageryState.invalid {
76 | // ancestor is still loading
77 | closestAncestorThatNeedsLoading = closestAncestorThatNeedsLoading ?? ancestor!
78 | }
79 | ancestor = ancestor!.parent
80 | }
81 |
82 | if readyImagery !== ancestor {
83 | if let readyImagery = readyImagery {
84 | readyImagery.releaseReference()
85 | }
86 |
87 | readyImagery = ancestor
88 |
89 | if let ancestor = ancestor {
90 | ancestor.addReference()
91 | textureTranslationAndScale = imageryLayer.calculateTextureTranslationAndScale(tile, tileImagery: self)
92 | }
93 | }
94 |
95 | if loadingImagery!.state == .failed || loadingImagery!.state == .invalid {
96 | if let closestAncestorThatNeedsLoading = closestAncestorThatNeedsLoading {
97 | // Push the ancestor's load process along a bit. This is necessary because some ancestor imagery
98 | // tiles may not be attached directly to a terrain tile. Such tiles will never load if
99 | // we don't do it here.
100 | closestAncestorThatNeedsLoading.processStateMachine(frameState: &frameState)
101 | return false
102 | } else {
103 | // This imagery tile is failed or invalid, and we have the "best available" substitute. So we're done loading.
104 | return true // done loading
105 | }
106 | }
107 | return false // not done loading
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/CesiumKit/Scene/FXAA.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FXAA.swift
3 | // CesiumKit
4 | //
5 | // Created by Ryan Walklin on 20/11/2015.
6 | // Copyright © 2015 Test Toast. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import MetalKit
11 |
12 | class FXAA {
13 | /**
14 | * @private
15 | */
16 | fileprivate var _texture: Texture? = nil
17 | fileprivate var _depthTexture: Texture? = nil
18 |
19 | fileprivate var _fbo: Framebuffer? = nil
20 | fileprivate var _command: DrawCommand? = nil
21 |
22 | fileprivate var _clearCommand: ClearCommand
23 |
24 | init () {
25 | _clearCommand = ClearCommand(
26 | color : Cartesian4(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0),
27 | depth : 1.0
28 | )
29 | _clearCommand.owner = self
30 | }
31 |
32 | func update (_ context: Context) {
33 | let width = context.width
34 | let height = context.height
35 |
36 | let textureChanged = _texture == nil || _texture!.width != width || _texture!.height != height
37 | if textureChanged {
38 | _depthTexture = nil
39 |
40 | _texture = Texture(
41 | context: context,
42 | options: TextureOptions(
43 | width: width,
44 | height: height,
45 | usage: [.ShaderRead, .RenderTarget])
46 | )
47 |
48 | if context.depthTexture {
49 | _depthTexture = Texture(
50 | context: context,
51 | options: TextureOptions(
52 | width: width,
53 | height: height,
54 | pixelFormat: .depth32FloatStencil8,
55 | usage: .RenderTarget)
56 | )
57 | }
58 | }
59 |
60 | if _fbo == nil || textureChanged {
61 |
62 | _fbo = Framebuffer(
63 | maximumColorAttachments: 1,
64 | colorTextures : [_texture!],
65 | depthTexture : _depthTexture
66 | )
67 | }
68 |
69 | if _command == nil {
70 | var overrides = ViewportQuadOverrides()
71 | overrides.renderState = RenderState(device: context.device)
72 | overrides.owner = self
73 | _command = context.createViewportQuadCommand(
74 | fragmentShaderSource: ShaderSource(sources: [Shaders["FXAAFS"]!]),
75 | overrides: overrides
76 | )
77 | }
78 |
79 | if textureChanged {
80 | let uniformMap = FXAAUniformMap()
81 | uniformMap.texture = _texture
82 | uniformMap.step = Cartesian2(x: 1.0 / Double(_texture!.width), y: 1.0 / Double(_texture!.height))
83 | uniformMap.uniformBufferProvider = _command!.pipeline!.shaderProgram.createUniformBufferProvider(context.device, deallocationBlock: nil)
84 | _command!.uniformMap = uniformMap
85 | }
86 | }
87 |
88 | func execute (_ context: Context, renderPass: RenderPass) {
89 | _command!.execute(context, renderPass: renderPass)
90 | }
91 |
92 | func clear (_ context: Context, passState: PassState, clearColor: Cartesian4) {
93 | let framebuffer = passState.framebuffer
94 |
95 | passState.framebuffer = _fbo
96 | _clearCommand.color = clearColor
97 | _clearCommand.execute(context, passState: passState)
98 |
99 | passState.framebuffer = framebuffer
100 | }
101 |
102 |
103 | func getColorFramebuffer() -> Framebuffer? {
104 | return _fbo
105 | }
106 |
107 | }
108 |
109 | private struct FXAAUniformStruct: UniformStruct {
110 | var step = float2()
111 | }
112 |
113 | class FXAAUniformMap: NativeUniformMap {
114 |
115 | var step: Cartesian2 {
116 | get {
117 | return Cartesian2(simd: simd_double(_uniformStruct.step))
118 | }
119 | set {
120 | _uniformStruct.step = newValue.floatRepresentation
121 | }
122 | }
123 |
124 | var texture : Texture?
125 |
126 | var uniformBufferProvider: UniformBufferProvider! = nil
127 |
128 | fileprivate var _uniformStruct = FXAAUniformStruct()
129 |
130 | var uniformDescriptors: [UniformDescriptor] = [
131 | UniformDescriptor(name: "u_step", type: .floatVec2, count: 1)
132 | ]
133 |
134 | lazy var uniformUpdateBlock: UniformUpdateBlock = { buffer in
135 | buffer.write(from: &self._uniformStruct, length: MemoryLayout.size)
136 | return [self.texture!]
137 | }
138 |
139 | }
140 |
141 |
--------------------------------------------------------------------------------