├── code ├── ARKit Demo │ ├── ARKit Demo.xcodeproj │ │ └── project.pbxproj │ ├── ARKit Demo │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ViewController.swift │ │ ├── ball.png │ │ ├── earth.png │ │ ├── monster.png │ │ └── moon.jpg │ ├── readme.md │ └── screenshot.png ├── SceneKit Standalone │ ├── SceneKit Standalone.xcodeproj │ │ └── project.pbxproj │ ├── SceneKit Standalone │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ViewController.swift │ │ ├── earth.png │ │ └── moon.jpg │ ├── readme.md │ └── screenshot.png └── SpriteKit Standalone │ ├── SpriteKit Standalone.xcodeproj │ └── project.pbxproj │ ├── SpriteKit Standalone │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.swift │ ├── ball.png │ └── monster.png │ ├── readme.md │ └── screenshot.png ├── readme.md ├── slides.pdf ├── title.png └── videos ├── Video A.MOV ├── Video B.MP4 ├── Video C.mov ├── Video D.MOV ├── Video E.MOV ├── Video F.MP4 ├── Video G.MP4 ├── Video H.mp4 ├── Video I.mp4 ├── Video J.mp4 ├── Video K.mov └── Video L.mov /code/ARKit Demo/ARKit Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DD7243511F9FDBCE00F286EB /* earth.png in Resources */ = {isa = PBXBuildFile; fileRef = DD7243501F9FDB9C00F286EB /* earth.png */; }; 11 | DD7243521F9FDBCE00F286EB /* moon.jpg in Resources */ = {isa = PBXBuildFile; fileRef = DD72434F1F9FDB9C00F286EB /* moon.jpg */; }; 12 | DD7243551F9FDE1B00F286EB /* monster.png in Resources */ = {isa = PBXBuildFile; fileRef = DD7243531F9FDE1200F286EB /* monster.png */; }; 13 | DD7243561F9FDE1C00F286EB /* ball.png in Resources */ = {isa = PBXBuildFile; fileRef = DD7243541F9FDE1600F286EB /* ball.png */; }; 14 | DD7EB6371F9FC884007E238E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7EB6361F9FC884007E238E /* AppDelegate.swift */; }; 15 | DD7EB6391F9FC884007E238E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7EB6381F9FC884007E238E /* ViewController.swift */; }; 16 | DD7EB63C1F9FC884007E238E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD7EB63A1F9FC884007E238E /* Main.storyboard */; }; 17 | DD7EB63E1F9FC884007E238E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD7EB63D1F9FC884007E238E /* Assets.xcassets */; }; 18 | DD7EB6411F9FC884007E238E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD7EB63F1F9FC884007E238E /* LaunchScreen.storyboard */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | DD72434F1F9FDB9C00F286EB /* moon.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = moon.jpg; sourceTree = ""; }; 23 | DD7243501F9FDB9C00F286EB /* earth.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = earth.png; sourceTree = ""; }; 24 | DD7243531F9FDE1200F286EB /* monster.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = monster.png; sourceTree = ""; }; 25 | DD7243541F9FDE1600F286EB /* ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ball.png; sourceTree = ""; }; 26 | DD7EB6331F9FC884007E238E /* ARKit Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ARKit Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | DD7EB6361F9FC884007E238E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 28 | DD7EB6381F9FC884007E238E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 29 | DD7EB63B1F9FC884007E238E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | DD7EB63D1F9FC884007E238E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | DD7EB6401F9FC884007E238E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | DD7EB6421F9FC884007E238E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | DD7EB6301F9FC884007E238E /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | DD7EB62A1F9FC884007E238E = { 47 | isa = PBXGroup; 48 | children = ( 49 | DD7EB6351F9FC884007E238E /* ARKit Demo */, 50 | DD7EB6341F9FC884007E238E /* Products */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | DD7EB6341F9FC884007E238E /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | DD7EB6331F9FC884007E238E /* ARKit Demo.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | DD7EB6351F9FC884007E238E /* ARKit Demo */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | DD7EB6361F9FC884007E238E /* AppDelegate.swift */, 66 | DD7EB6381F9FC884007E238E /* ViewController.swift */, 67 | DD7EB63A1F9FC884007E238E /* Main.storyboard */, 68 | DD7EB63D1F9FC884007E238E /* Assets.xcassets */, 69 | DD7EB63F1F9FC884007E238E /* LaunchScreen.storyboard */, 70 | DD7EB6421F9FC884007E238E /* Info.plist */, 71 | DD7243531F9FDE1200F286EB /* monster.png */, 72 | DD7243541F9FDE1600F286EB /* ball.png */, 73 | DD7243501F9FDB9C00F286EB /* earth.png */, 74 | DD72434F1F9FDB9C00F286EB /* moon.jpg */, 75 | ); 76 | path = "ARKit Demo"; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | DD7EB6321F9FC884007E238E /* ARKit Demo */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = DD7EB6451F9FC884007E238E /* Build configuration list for PBXNativeTarget "ARKit Demo" */; 85 | buildPhases = ( 86 | DD7EB62F1F9FC884007E238E /* Sources */, 87 | DD7EB6301F9FC884007E238E /* Frameworks */, 88 | DD7EB6311F9FC884007E238E /* Resources */, 89 | ); 90 | buildRules = ( 91 | ); 92 | dependencies = ( 93 | ); 94 | name = "ARKit Demo"; 95 | productName = "ARKit Demo"; 96 | productReference = DD7EB6331F9FC884007E238E /* ARKit Demo.app */; 97 | productType = "com.apple.product-type.application"; 98 | }; 99 | /* End PBXNativeTarget section */ 100 | 101 | /* Begin PBXProject section */ 102 | DD7EB62B1F9FC884007E238E /* Project object */ = { 103 | isa = PBXProject; 104 | attributes = { 105 | LastSwiftUpdateCheck = 0900; 106 | LastUpgradeCheck = 0900; 107 | ORGANIZATIONNAME = "Justin R. Miller"; 108 | TargetAttributes = { 109 | DD7EB6321F9FC884007E238E = { 110 | CreatedOnToolsVersion = 9.0; 111 | ProvisioningStyle = Automatic; 112 | }; 113 | }; 114 | }; 115 | buildConfigurationList = DD7EB62E1F9FC884007E238E /* Build configuration list for PBXProject "ARKit Demo" */; 116 | compatibilityVersion = "Xcode 8.0"; 117 | developmentRegion = en; 118 | hasScannedForEncodings = 0; 119 | knownRegions = ( 120 | en, 121 | Base, 122 | ); 123 | mainGroup = DD7EB62A1F9FC884007E238E; 124 | productRefGroup = DD7EB6341F9FC884007E238E /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | DD7EB6321F9FC884007E238E /* ARKit Demo */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXResourcesBuildPhase section */ 134 | DD7EB6311F9FC884007E238E /* Resources */ = { 135 | isa = PBXResourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | DD7EB6411F9FC884007E238E /* LaunchScreen.storyboard in Resources */, 139 | DD7EB63E1F9FC884007E238E /* Assets.xcassets in Resources */, 140 | DD7EB63C1F9FC884007E238E /* Main.storyboard in Resources */, 141 | DD7243551F9FDE1B00F286EB /* monster.png in Resources */, 142 | DD7243561F9FDE1C00F286EB /* ball.png in Resources */, 143 | DD7243511F9FDBCE00F286EB /* earth.png in Resources */, 144 | DD7243521F9FDBCE00F286EB /* moon.jpg in Resources */, 145 | ); 146 | runOnlyForDeploymentPostprocessing = 0; 147 | }; 148 | /* End PBXResourcesBuildPhase section */ 149 | 150 | /* Begin PBXSourcesBuildPhase section */ 151 | DD7EB62F1F9FC884007E238E /* Sources */ = { 152 | isa = PBXSourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | DD7EB6391F9FC884007E238E /* ViewController.swift in Sources */, 156 | DD7EB6371F9FC884007E238E /* AppDelegate.swift in Sources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXSourcesBuildPhase section */ 161 | 162 | /* Begin PBXVariantGroup section */ 163 | DD7EB63A1F9FC884007E238E /* Main.storyboard */ = { 164 | isa = PBXVariantGroup; 165 | children = ( 166 | DD7EB63B1F9FC884007E238E /* Base */, 167 | ); 168 | name = Main.storyboard; 169 | sourceTree = ""; 170 | }; 171 | DD7EB63F1F9FC884007E238E /* LaunchScreen.storyboard */ = { 172 | isa = PBXVariantGroup; 173 | children = ( 174 | DD7EB6401F9FC884007E238E /* Base */, 175 | ); 176 | name = LaunchScreen.storyboard; 177 | sourceTree = ""; 178 | }; 179 | /* End PBXVariantGroup section */ 180 | 181 | /* Begin XCBuildConfiguration section */ 182 | DD7EB6431F9FC884007E238E /* Debug */ = { 183 | isa = XCBuildConfiguration; 184 | buildSettings = { 185 | ALWAYS_SEARCH_USER_PATHS = NO; 186 | CLANG_ANALYZER_NONNULL = YES; 187 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 188 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 189 | CLANG_CXX_LIBRARY = "libc++"; 190 | CLANG_ENABLE_MODULES = YES; 191 | CLANG_ENABLE_OBJC_ARC = YES; 192 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 193 | CLANG_WARN_BOOL_CONVERSION = YES; 194 | CLANG_WARN_COMMA = YES; 195 | CLANG_WARN_CONSTANT_CONVERSION = YES; 196 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 197 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 198 | CLANG_WARN_EMPTY_BODY = YES; 199 | CLANG_WARN_ENUM_CONVERSION = YES; 200 | CLANG_WARN_INFINITE_RECURSION = YES; 201 | CLANG_WARN_INT_CONVERSION = YES; 202 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 203 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 204 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 205 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 206 | CLANG_WARN_STRICT_PROTOTYPES = YES; 207 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 208 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 209 | CLANG_WARN_UNREACHABLE_CODE = YES; 210 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 211 | CODE_SIGN_IDENTITY = "iPhone Developer"; 212 | COPY_PHASE_STRIP = NO; 213 | DEBUG_INFORMATION_FORMAT = dwarf; 214 | ENABLE_STRICT_OBJC_MSGSEND = YES; 215 | ENABLE_TESTABILITY = YES; 216 | GCC_C_LANGUAGE_STANDARD = gnu11; 217 | GCC_DYNAMIC_NO_PIC = NO; 218 | GCC_NO_COMMON_BLOCKS = YES; 219 | GCC_OPTIMIZATION_LEVEL = 0; 220 | GCC_PREPROCESSOR_DEFINITIONS = ( 221 | "DEBUG=1", 222 | "$(inherited)", 223 | ); 224 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 225 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 226 | GCC_WARN_UNDECLARED_SELECTOR = YES; 227 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 228 | GCC_WARN_UNUSED_FUNCTION = YES; 229 | GCC_WARN_UNUSED_VARIABLE = YES; 230 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 231 | MTL_ENABLE_DEBUG_INFO = YES; 232 | ONLY_ACTIVE_ARCH = YES; 233 | SDKROOT = iphoneos; 234 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 235 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 236 | }; 237 | name = Debug; 238 | }; 239 | DD7EB6441F9FC884007E238E /* Release */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ALWAYS_SEARCH_USER_PATHS = NO; 243 | CLANG_ANALYZER_NONNULL = YES; 244 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 250 | CLANG_WARN_BOOL_CONVERSION = YES; 251 | CLANG_WARN_COMMA = YES; 252 | CLANG_WARN_CONSTANT_CONVERSION = YES; 253 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 254 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 255 | CLANG_WARN_EMPTY_BODY = YES; 256 | CLANG_WARN_ENUM_CONVERSION = YES; 257 | CLANG_WARN_INFINITE_RECURSION = YES; 258 | CLANG_WARN_INT_CONVERSION = YES; 259 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 261 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 262 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 263 | CLANG_WARN_STRICT_PROTOTYPES = YES; 264 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 265 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 266 | CLANG_WARN_UNREACHABLE_CODE = YES; 267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 268 | CODE_SIGN_IDENTITY = "iPhone Developer"; 269 | COPY_PHASE_STRIP = NO; 270 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 271 | ENABLE_NS_ASSERTIONS = NO; 272 | ENABLE_STRICT_OBJC_MSGSEND = YES; 273 | GCC_C_LANGUAGE_STANDARD = gnu11; 274 | GCC_NO_COMMON_BLOCKS = YES; 275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 277 | GCC_WARN_UNDECLARED_SELECTOR = YES; 278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 279 | GCC_WARN_UNUSED_FUNCTION = YES; 280 | GCC_WARN_UNUSED_VARIABLE = YES; 281 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 282 | MTL_ENABLE_DEBUG_INFO = NO; 283 | SDKROOT = iphoneos; 284 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 285 | VALIDATE_PRODUCT = YES; 286 | }; 287 | name = Release; 288 | }; 289 | DD7EB6461F9FC884007E238E /* Debug */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 293 | CODE_SIGN_STYLE = Automatic; 294 | DEVELOPMENT_TEAM = BCEFQF8MNF; 295 | INFOPLIST_FILE = "ARKit Demo/Info.plist"; 296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 297 | PRODUCT_BUNDLE_IDENTIFIER = "io.justinmiller.ARKit-Demo"; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | SWIFT_VERSION = 4.0; 300 | TARGETED_DEVICE_FAMILY = "1,2"; 301 | }; 302 | name = Debug; 303 | }; 304 | DD7EB6471F9FC884007E238E /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 308 | CODE_SIGN_STYLE = Automatic; 309 | DEVELOPMENT_TEAM = BCEFQF8MNF; 310 | INFOPLIST_FILE = "ARKit Demo/Info.plist"; 311 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 312 | PRODUCT_BUNDLE_IDENTIFIER = "io.justinmiller.ARKit-Demo"; 313 | PRODUCT_NAME = "$(TARGET_NAME)"; 314 | SWIFT_VERSION = 4.0; 315 | TARGETED_DEVICE_FAMILY = "1,2"; 316 | }; 317 | name = Release; 318 | }; 319 | /* End XCBuildConfiguration section */ 320 | 321 | /* Begin XCConfigurationList section */ 322 | DD7EB62E1F9FC884007E238E /* Build configuration list for PBXProject "ARKit Demo" */ = { 323 | isa = XCConfigurationList; 324 | buildConfigurations = ( 325 | DD7EB6431F9FC884007E238E /* Debug */, 326 | DD7EB6441F9FC884007E238E /* Release */, 327 | ); 328 | defaultConfigurationIsVisible = 0; 329 | defaultConfigurationName = Release; 330 | }; 331 | DD7EB6451F9FC884007E238E /* Build configuration list for PBXNativeTarget "ARKit Demo" */ = { 332 | isa = XCConfigurationList; 333 | buildConfigurations = ( 334 | DD7EB6461F9FC884007E238E /* Debug */, 335 | DD7EB6471F9FC884007E238E /* Release */, 336 | ); 337 | defaultConfigurationIsVisible = 0; 338 | defaultConfigurationName = Release; 339 | }; 340 | /* End XCConfigurationList section */ 341 | }; 342 | rootObject = DD7EB62B1F9FC884007E238E /* Project object */; 343 | } 344 | -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { 4 | 5 | var window: UIWindow? 6 | 7 | } 8 | -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | NSCameraUsageDescription 38 | The camera will be used for augmented reality. 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import ARKit 3 | 4 | class ViewController: UIViewController, ARSKViewDelegate, ARSCNViewDelegate { 5 | 6 | let BASE_VIEW = ARSCNView.self // change this between ARSKView & ARSCNView to swap kits 7 | 8 | var arSpriteView: ARSKView! 9 | var arSceneView: ARSCNView! 10 | 11 | override func viewDidLoad() { 12 | super.viewDidLoad() 13 | setupARSession() 14 | } 15 | 16 | func setupARSession() { 17 | guard ARWorldTrackingConfiguration.isSupported else { 18 | fatalError("ARKit is not available on this device.") 19 | } 20 | 21 | if BASE_VIEW == ARSKView.self { 22 | arSpriteView = ARSKView(frame: view.bounds) 23 | arSpriteView.delegate = self 24 | view.addSubview(arSpriteView) 25 | 26 | let scene = SKScene(size: arSpriteView.bounds.size) 27 | scene.scaleMode = .resizeFill 28 | scene.anchorPoint = CGPoint(x: 0.5, y: 0.5) 29 | arSpriteView.presentScene(scene) 30 | 31 | let configuration = ARWorldTrackingConfiguration() 32 | arSpriteView.session.run(configuration, options: []) 33 | 34 | arSpriteView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))) 35 | } else if BASE_VIEW == ARSCNView.self { 36 | arSceneView = ARSCNView(frame: view.bounds) 37 | arSceneView.autoenablesDefaultLighting = true 38 | arSceneView.delegate = self 39 | view.addSubview(arSceneView) 40 | 41 | let configuration = ARWorldTrackingConfiguration() 42 | arSceneView.session.run(configuration, options: []) 43 | 44 | arSceneView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))) 45 | } 46 | } 47 | 48 | @objc func handleTap(_ tap: UITapGestureRecognizer) { 49 | if BASE_VIEW == ARSKView.self { 50 | if let _ = arSpriteView.hitTest(tap.location(in: tap.view), types: [.estimatedHorizontalPlane]).first { 51 | // detect the closest tapped horizontal plane, then set the sprite anchor two meters in front of the current camera position & orientation 52 | var translation = matrix_identity_float4x4 53 | translation.columns.3.z = -2 54 | let transform = simd_mul(arSpriteView.session.currentFrame!.camera.transform, translation) 55 | let anchor = ARAnchor(transform: transform) 56 | arSpriteView.session.add(anchor: anchor) 57 | } 58 | } else if BASE_VIEW == ARSCNView.self { 59 | if let hit = arSceneView.hitTest(tap.location(in: tap.view), types: [.estimatedHorizontalPlane]).first { 60 | // detect the closest tapped horizontal plane, then set the geometry anchor at the tap point 61 | let transform = hit.worldTransform 62 | let anchor = ARAnchor(transform: transform) 63 | arSceneView.session.add(anchor: anchor) 64 | } 65 | } 66 | } 67 | 68 | // only used for SpriteKit 69 | func view(_ view: ARSKView, nodeFor anchor: ARAnchor) -> SKNode? { 70 | let sprite = SKSpriteNode(imageNamed: "monster.png") 71 | return sprite 72 | } 73 | 74 | // only used for SceneKit 75 | func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? { 76 | let cube = SCNBox(width: 0.05, height: 0.05, length: 0.05, chamferRadius: 0) 77 | cube.firstMaterial!.diffuse.contents = UIColor.blue 78 | let node = SCNNode(geometry: cube) 79 | node.simdTransform = anchor.transform 80 | return node 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/ARKit Demo/ARKit Demo/ball.png -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/ARKit Demo/ARKit Demo/earth.png -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/monster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/ARKit Demo/ARKit Demo/monster.png -------------------------------------------------------------------------------- /code/ARKit Demo/ARKit Demo/moon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/ARKit Demo/ARKit Demo/moon.jpg -------------------------------------------------------------------------------- /code/ARKit Demo/readme.md: -------------------------------------------------------------------------------- 1 | # ARKit Demo 2 | 3 | First, choose SpriteKit (2D) or SceneKit (3D) by changing the line near the top of the view controller, then rebuilding. 4 | 5 | On an ARKit-supported device, start the app, then point the device's camera at a horizontal plane like a floor or tabletop. When you tap the object in the view, with SpriteKit, you should get a 2D sprite of a monster at that point in augmented reality. With SceneKit, you should get a 5cm blue cube placed on the plane. 6 | 7 | ![](screenshot.png) 8 | -------------------------------------------------------------------------------- /code/ARKit Demo/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/ARKit Demo/screenshot.png -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DD06B3821F98375100E46FFE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD06B3811F98375100E46FFE /* AppDelegate.swift */; }; 11 | DD06B3841F98375100E46FFE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD06B3831F98375100E46FFE /* ViewController.swift */; }; 12 | DD06B3871F98375100E46FFE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD06B3851F98375100E46FFE /* Main.storyboard */; }; 13 | DD06B3891F98375100E46FFE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD06B3881F98375100E46FFE /* Assets.xcassets */; }; 14 | DD06B38C1F98375100E46FFE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD06B38A1F98375100E46FFE /* LaunchScreen.storyboard */; }; 15 | DDADE39B1F9985D60030577E /* moon.jpg in Resources */ = {isa = PBXBuildFile; fileRef = DDADE3971F99855B0030577E /* moon.jpg */; }; 16 | DDADE39D1F9986F80030577E /* earth.png in Resources */ = {isa = PBXBuildFile; fileRef = DDADE39C1F9986C90030577E /* earth.png */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | DD06B37E1F98375100E46FFE /* SceneKit Standalone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SceneKit Standalone.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | DD06B3811F98375100E46FFE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | DD06B3831F98375100E46FFE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 23 | DD06B3861F98375100E46FFE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 24 | DD06B3881F98375100E46FFE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 25 | DD06B38B1F98375100E46FFE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 26 | DD06B38D1F98375100E46FFE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | DDADE3971F99855B0030577E /* moon.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = moon.jpg; sourceTree = ""; }; 28 | DDADE39C1F9986C90030577E /* earth.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = earth.png; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | DD06B37B1F98375100E46FFE /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | DD06B3751F98375100E46FFE = { 43 | isa = PBXGroup; 44 | children = ( 45 | DD06B3801F98375100E46FFE /* SceneKit Standalone */, 46 | DD06B37F1F98375100E46FFE /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | DD06B37F1F98375100E46FFE /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | DD06B37E1F98375100E46FFE /* SceneKit Standalone.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | DD06B3801F98375100E46FFE /* SceneKit Standalone */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | DD06B3811F98375100E46FFE /* AppDelegate.swift */, 62 | DD06B3831F98375100E46FFE /* ViewController.swift */, 63 | DD06B3851F98375100E46FFE /* Main.storyboard */, 64 | DD06B3881F98375100E46FFE /* Assets.xcassets */, 65 | DD06B38A1F98375100E46FFE /* LaunchScreen.storyboard */, 66 | DD06B38D1F98375100E46FFE /* Info.plist */, 67 | DDADE39C1F9986C90030577E /* earth.png */, 68 | DDADE3971F99855B0030577E /* moon.jpg */, 69 | ); 70 | path = "SceneKit Standalone"; 71 | sourceTree = ""; 72 | }; 73 | /* End PBXGroup section */ 74 | 75 | /* Begin PBXNativeTarget section */ 76 | DD06B37D1F98375100E46FFE /* SceneKit Standalone */ = { 77 | isa = PBXNativeTarget; 78 | buildConfigurationList = DD06B3901F98375100E46FFE /* Build configuration list for PBXNativeTarget "SceneKit Standalone" */; 79 | buildPhases = ( 80 | DD06B37A1F98375100E46FFE /* Sources */, 81 | DD06B37B1F98375100E46FFE /* Frameworks */, 82 | DD06B37C1F98375100E46FFE /* Resources */, 83 | ); 84 | buildRules = ( 85 | ); 86 | dependencies = ( 87 | ); 88 | name = "SceneKit Standalone"; 89 | productName = "SceneKit Standalone"; 90 | productReference = DD06B37E1F98375100E46FFE /* SceneKit Standalone.app */; 91 | productType = "com.apple.product-type.application"; 92 | }; 93 | /* End PBXNativeTarget section */ 94 | 95 | /* Begin PBXProject section */ 96 | DD06B3761F98375100E46FFE /* Project object */ = { 97 | isa = PBXProject; 98 | attributes = { 99 | LastSwiftUpdateCheck = 0900; 100 | LastUpgradeCheck = 0900; 101 | ORGANIZATIONNAME = "Justin R. Miller"; 102 | TargetAttributes = { 103 | DD06B37D1F98375100E46FFE = { 104 | CreatedOnToolsVersion = 9.0; 105 | ProvisioningStyle = Automatic; 106 | }; 107 | }; 108 | }; 109 | buildConfigurationList = DD06B3791F98375100E46FFE /* Build configuration list for PBXProject "SceneKit Standalone" */; 110 | compatibilityVersion = "Xcode 8.0"; 111 | developmentRegion = en; 112 | hasScannedForEncodings = 0; 113 | knownRegions = ( 114 | en, 115 | Base, 116 | ); 117 | mainGroup = DD06B3751F98375100E46FFE; 118 | productRefGroup = DD06B37F1F98375100E46FFE /* Products */; 119 | projectDirPath = ""; 120 | projectRoot = ""; 121 | targets = ( 122 | DD06B37D1F98375100E46FFE /* SceneKit Standalone */, 123 | ); 124 | }; 125 | /* End PBXProject section */ 126 | 127 | /* Begin PBXResourcesBuildPhase section */ 128 | DD06B37C1F98375100E46FFE /* Resources */ = { 129 | isa = PBXResourcesBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | DD06B38C1F98375100E46FFE /* LaunchScreen.storyboard in Resources */, 133 | DD06B3891F98375100E46FFE /* Assets.xcassets in Resources */, 134 | DD06B3871F98375100E46FFE /* Main.storyboard in Resources */, 135 | DDADE39D1F9986F80030577E /* earth.png in Resources */, 136 | DDADE39B1F9985D60030577E /* moon.jpg in Resources */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXResourcesBuildPhase section */ 141 | 142 | /* Begin PBXSourcesBuildPhase section */ 143 | DD06B37A1F98375100E46FFE /* Sources */ = { 144 | isa = PBXSourcesBuildPhase; 145 | buildActionMask = 2147483647; 146 | files = ( 147 | DD06B3841F98375100E46FFE /* ViewController.swift in Sources */, 148 | DD06B3821F98375100E46FFE /* AppDelegate.swift in Sources */, 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXSourcesBuildPhase section */ 153 | 154 | /* Begin PBXVariantGroup section */ 155 | DD06B3851F98375100E46FFE /* Main.storyboard */ = { 156 | isa = PBXVariantGroup; 157 | children = ( 158 | DD06B3861F98375100E46FFE /* Base */, 159 | ); 160 | name = Main.storyboard; 161 | sourceTree = ""; 162 | }; 163 | DD06B38A1F98375100E46FFE /* LaunchScreen.storyboard */ = { 164 | isa = PBXVariantGroup; 165 | children = ( 166 | DD06B38B1F98375100E46FFE /* Base */, 167 | ); 168 | name = LaunchScreen.storyboard; 169 | sourceTree = ""; 170 | }; 171 | /* End PBXVariantGroup section */ 172 | 173 | /* Begin XCBuildConfiguration section */ 174 | DD06B38E1F98375100E46FFE /* Debug */ = { 175 | isa = XCBuildConfiguration; 176 | buildSettings = { 177 | ALWAYS_SEARCH_USER_PATHS = NO; 178 | CLANG_ANALYZER_NONNULL = YES; 179 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 181 | CLANG_CXX_LIBRARY = "libc++"; 182 | CLANG_ENABLE_MODULES = YES; 183 | CLANG_ENABLE_OBJC_ARC = YES; 184 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 185 | CLANG_WARN_BOOL_CONVERSION = YES; 186 | CLANG_WARN_COMMA = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 189 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 190 | CLANG_WARN_EMPTY_BODY = YES; 191 | CLANG_WARN_ENUM_CONVERSION = YES; 192 | CLANG_WARN_INFINITE_RECURSION = YES; 193 | CLANG_WARN_INT_CONVERSION = YES; 194 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 195 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 196 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 197 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 198 | CLANG_WARN_STRICT_PROTOTYPES = YES; 199 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 200 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 201 | CLANG_WARN_UNREACHABLE_CODE = YES; 202 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 203 | CODE_SIGN_IDENTITY = "iPhone Developer"; 204 | COPY_PHASE_STRIP = NO; 205 | DEBUG_INFORMATION_FORMAT = dwarf; 206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 207 | ENABLE_TESTABILITY = YES; 208 | GCC_C_LANGUAGE_STANDARD = gnu11; 209 | GCC_DYNAMIC_NO_PIC = NO; 210 | GCC_NO_COMMON_BLOCKS = YES; 211 | GCC_OPTIMIZATION_LEVEL = 0; 212 | GCC_PREPROCESSOR_DEFINITIONS = ( 213 | "DEBUG=1", 214 | "$(inherited)", 215 | ); 216 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 217 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 218 | GCC_WARN_UNDECLARED_SELECTOR = YES; 219 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 220 | GCC_WARN_UNUSED_FUNCTION = YES; 221 | GCC_WARN_UNUSED_VARIABLE = YES; 222 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 223 | MTL_ENABLE_DEBUG_INFO = YES; 224 | ONLY_ACTIVE_ARCH = YES; 225 | SDKROOT = iphoneos; 226 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 227 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 228 | }; 229 | name = Debug; 230 | }; 231 | DD06B38F1F98375100E46FFE /* Release */ = { 232 | isa = XCBuildConfiguration; 233 | buildSettings = { 234 | ALWAYS_SEARCH_USER_PATHS = NO; 235 | CLANG_ANALYZER_NONNULL = YES; 236 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 238 | CLANG_CXX_LIBRARY = "libc++"; 239 | CLANG_ENABLE_MODULES = YES; 240 | CLANG_ENABLE_OBJC_ARC = YES; 241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_COMMA = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 246 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 247 | CLANG_WARN_EMPTY_BODY = YES; 248 | CLANG_WARN_ENUM_CONVERSION = YES; 249 | CLANG_WARN_INFINITE_RECURSION = YES; 250 | CLANG_WARN_INT_CONVERSION = YES; 251 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 253 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 254 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 255 | CLANG_WARN_STRICT_PROTOTYPES = YES; 256 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 257 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | CODE_SIGN_IDENTITY = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 263 | ENABLE_NS_ASSERTIONS = NO; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu11; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 274 | MTL_ENABLE_DEBUG_INFO = NO; 275 | SDKROOT = iphoneos; 276 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 277 | VALIDATE_PRODUCT = YES; 278 | }; 279 | name = Release; 280 | }; 281 | DD06B3911F98375100E46FFE /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | CODE_SIGN_STYLE = Automatic; 286 | DEVELOPMENT_TEAM = BCEFQF8MNF; 287 | INFOPLIST_FILE = "SceneKit Standalone/Info.plist"; 288 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 289 | PRODUCT_BUNDLE_IDENTIFIER = "io.justinmiller.SceneKit-Standalone"; 290 | PRODUCT_NAME = "$(TARGET_NAME)"; 291 | SWIFT_VERSION = 4.0; 292 | TARGETED_DEVICE_FAMILY = "1,2"; 293 | }; 294 | name = Debug; 295 | }; 296 | DD06B3921F98375100E46FFE /* Release */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CODE_SIGN_STYLE = Automatic; 301 | DEVELOPMENT_TEAM = BCEFQF8MNF; 302 | INFOPLIST_FILE = "SceneKit Standalone/Info.plist"; 303 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 304 | PRODUCT_BUNDLE_IDENTIFIER = "io.justinmiller.SceneKit-Standalone"; 305 | PRODUCT_NAME = "$(TARGET_NAME)"; 306 | SWIFT_VERSION = 4.0; 307 | TARGETED_DEVICE_FAMILY = "1,2"; 308 | }; 309 | name = Release; 310 | }; 311 | /* End XCBuildConfiguration section */ 312 | 313 | /* Begin XCConfigurationList section */ 314 | DD06B3791F98375100E46FFE /* Build configuration list for PBXProject "SceneKit Standalone" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | DD06B38E1F98375100E46FFE /* Debug */, 318 | DD06B38F1F98375100E46FFE /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | defaultConfigurationName = Release; 322 | }; 323 | DD06B3901F98375100E46FFE /* Build configuration list for PBXNativeTarget "SceneKit Standalone" */ = { 324 | isa = XCConfigurationList; 325 | buildConfigurations = ( 326 | DD06B3911F98375100E46FFE /* Debug */, 327 | DD06B3921F98375100E46FFE /* Release */, 328 | ); 329 | defaultConfigurationIsVisible = 0; 330 | defaultConfigurationName = Release; 331 | }; 332 | /* End XCConfigurationList section */ 333 | }; 334 | rootObject = DD06B3761F98375100E46FFE /* Project object */; 335 | } 336 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { 4 | 5 | var window: UIWindow? 6 | 7 | } 8 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | SceneKit Demo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SceneKit 3 | 4 | class ViewController: UIViewController { 5 | 6 | var sceneView: SCNView! 7 | var earth: SCNNode! 8 | var moon: SCNNode! 9 | 10 | override func viewDidLoad() { 11 | super.viewDidLoad() 12 | setupScene() 13 | } 14 | 15 | func setupScene() { 16 | sceneView = SCNView() 17 | sceneView.frame = view.bounds 18 | sceneView.backgroundColor = .black 19 | sceneView.allowsCameraControl = true 20 | view.addSubview(sceneView) 21 | 22 | let scene = SCNScene() 23 | sceneView.scene = scene 24 | 25 | sceneView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))) 26 | 27 | let sun = SCNNode() 28 | sun.position = SCNVector3Make(-500, 0, 0) 29 | sun.light = SCNLight() 30 | sun.light!.type = .omni 31 | scene.rootNode.addChildNode(sun) 32 | 33 | let earthGeometry = SCNSphere(radius: 10) 34 | earthGeometry.materials.first!.diffuse.contents = UIImage(named: "earth.png") 35 | earth = SCNNode(geometry: earthGeometry) 36 | earth.position = SCNVector3Make(0, 0, 0) 37 | scene.rootNode.addChildNode(earth) 38 | 39 | let moonRotator = SCNNode() 40 | moonRotator.position = SCNVector3Make(0, 0, 0) 41 | scene.rootNode.addChildNode(moonRotator) 42 | 43 | let moonGeometry = SCNSphere(radius: 2.5) 44 | moonGeometry.materials.first!.diffuse.contents = UIImage(named: "moon.jpg") 45 | moon = SCNNode(geometry: moonGeometry) 46 | moon.position = SCNVector3Make(50, 0, 0) 47 | moonRotator.addChildNode(moon) 48 | 49 | let moonOrbit = CABasicAnimation(keyPath: "rotation") 50 | moonOrbit.fromValue = moonRotator.rotation 51 | moonOrbit.toValue = SCNVector4Make(0, 1, 0, 2 * .pi) 52 | moonOrbit.duration = 3 * 28 53 | moonOrbit.repeatCount = .infinity 54 | moonRotator.addAnimation(moonOrbit, forKey: "rotation") 55 | 56 | let earthRotation = CABasicAnimation(keyPath: "rotation") 57 | earthRotation.fromValue = earth.rotation 58 | earthRotation.toValue = SCNVector4Make(0, 1, 0, 2 * .pi) 59 | earthRotation.duration = 3 60 | earthRotation.repeatCount = .infinity 61 | earth.addAnimation(earthRotation, forKey: "rotation") 62 | } 63 | 64 | @objc func handleTap(_ tap: UITapGestureRecognizer) { 65 | sceneView.scene!.isPaused = !sceneView.scene!.isPaused 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/SceneKit Standalone/SceneKit Standalone/earth.png -------------------------------------------------------------------------------- /code/SceneKit Standalone/SceneKit Standalone/moon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/SceneKit Standalone/SceneKit Standalone/moon.jpg -------------------------------------------------------------------------------- /code/SceneKit Standalone/readme.md: -------------------------------------------------------------------------------- 1 | # SceneKit Standalone 2 | 3 | The app displays two spheres, the Earth and the Moon. The Earth rotates on its axis and the moon revolves around it at 1/28th speed (one day versus one month). 4 | 5 | The relatively complex circular moon orbit path is accomplished using an invisible "moon rotator" node at the same point as the Earth. This node has the moon as its child. When rotated on its axis, it appears to make the Moon orbit the Earth. The same side always faces the Earth, but this mirrors real life since the Moon completes one rotation in the same time that it completes one orbit. 6 | 7 | Tap the screen to pause or resume the animation. At any point, you can use pinch gestures to zoom, a single-finger pan to rotate, and a two-finger pan to move the scene. 8 | 9 | ![](screenshot.png) 10 | -------------------------------------------------------------------------------- /code/SceneKit Standalone/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/SceneKit Standalone/screenshot.png -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DDADE3C91F999C340030577E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDADE3C81F999C340030577E /* AppDelegate.swift */; }; 11 | DDADE3CB1F999C340030577E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDADE3CA1F999C340030577E /* ViewController.swift */; }; 12 | DDADE3CE1F999C340030577E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDADE3CC1F999C340030577E /* Main.storyboard */; }; 13 | DDADE3D01F999C340030577E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDADE3CF1F999C340030577E /* Assets.xcassets */; }; 14 | DDADE3D31F999C340030577E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDADE3D11F999C340030577E /* LaunchScreen.storyboard */; }; 15 | DDADE3DC1F999D220030577E /* monster.png in Resources */ = {isa = PBXBuildFile; fileRef = DDADE3DA1F999D180030577E /* monster.png */; }; 16 | DDADE3DD1F999D250030577E /* ball.png in Resources */ = {isa = PBXBuildFile; fileRef = DDADE3DB1F999D180030577E /* ball.png */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | DDADE3C51F999C340030577E /* SpriteKit Standalone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SpriteKit Standalone.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | DDADE3C81F999C340030577E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | DDADE3CA1F999C340030577E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 23 | DDADE3CD1F999C340030577E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 24 | DDADE3CF1F999C340030577E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 25 | DDADE3D21F999C340030577E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 26 | DDADE3D41F999C340030577E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | DDADE3DA1F999D180030577E /* monster.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = monster.png; sourceTree = ""; }; 28 | DDADE3DB1F999D180030577E /* ball.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ball.png; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | DDADE3C21F999C340030577E /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | DDADE3BC1F999C330030577E = { 43 | isa = PBXGroup; 44 | children = ( 45 | DDADE3C71F999C340030577E /* SpriteKit Standalone */, 46 | DDADE3C61F999C340030577E /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | DDADE3C61F999C340030577E /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | DDADE3C51F999C340030577E /* SpriteKit Standalone.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | DDADE3C71F999C340030577E /* SpriteKit Standalone */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | DDADE3C81F999C340030577E /* AppDelegate.swift */, 62 | DDADE3CA1F999C340030577E /* ViewController.swift */, 63 | DDADE3CC1F999C340030577E /* Main.storyboard */, 64 | DDADE3CF1F999C340030577E /* Assets.xcassets */, 65 | DDADE3D11F999C340030577E /* LaunchScreen.storyboard */, 66 | DDADE3D41F999C340030577E /* Info.plist */, 67 | DDADE3DA1F999D180030577E /* monster.png */, 68 | DDADE3DB1F999D180030577E /* ball.png */, 69 | ); 70 | path = "SpriteKit Standalone"; 71 | sourceTree = ""; 72 | }; 73 | /* End PBXGroup section */ 74 | 75 | /* Begin PBXNativeTarget section */ 76 | DDADE3C41F999C340030577E /* SpriteKit Standalone */ = { 77 | isa = PBXNativeTarget; 78 | buildConfigurationList = DDADE3D71F999C340030577E /* Build configuration list for PBXNativeTarget "SpriteKit Standalone" */; 79 | buildPhases = ( 80 | DDADE3C11F999C340030577E /* Sources */, 81 | DDADE3C21F999C340030577E /* Frameworks */, 82 | DDADE3C31F999C340030577E /* Resources */, 83 | ); 84 | buildRules = ( 85 | ); 86 | dependencies = ( 87 | ); 88 | name = "SpriteKit Standalone"; 89 | productName = "SpriteKit Standalone"; 90 | productReference = DDADE3C51F999C340030577E /* SpriteKit Standalone.app */; 91 | productType = "com.apple.product-type.application"; 92 | }; 93 | /* End PBXNativeTarget section */ 94 | 95 | /* Begin PBXProject section */ 96 | DDADE3BD1F999C330030577E /* Project object */ = { 97 | isa = PBXProject; 98 | attributes = { 99 | LastSwiftUpdateCheck = 0900; 100 | LastUpgradeCheck = 0900; 101 | ORGANIZATIONNAME = "Justin R. Miller"; 102 | TargetAttributes = { 103 | DDADE3C41F999C340030577E = { 104 | CreatedOnToolsVersion = 9.0; 105 | ProvisioningStyle = Automatic; 106 | }; 107 | }; 108 | }; 109 | buildConfigurationList = DDADE3C01F999C330030577E /* Build configuration list for PBXProject "SpriteKit Standalone" */; 110 | compatibilityVersion = "Xcode 8.0"; 111 | developmentRegion = en; 112 | hasScannedForEncodings = 0; 113 | knownRegions = ( 114 | en, 115 | Base, 116 | ); 117 | mainGroup = DDADE3BC1F999C330030577E; 118 | productRefGroup = DDADE3C61F999C340030577E /* Products */; 119 | projectDirPath = ""; 120 | projectRoot = ""; 121 | targets = ( 122 | DDADE3C41F999C340030577E /* SpriteKit Standalone */, 123 | ); 124 | }; 125 | /* End PBXProject section */ 126 | 127 | /* Begin PBXResourcesBuildPhase section */ 128 | DDADE3C31F999C340030577E /* Resources */ = { 129 | isa = PBXResourcesBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | DDADE3D31F999C340030577E /* LaunchScreen.storyboard in Resources */, 133 | DDADE3D01F999C340030577E /* Assets.xcassets in Resources */, 134 | DDADE3CE1F999C340030577E /* Main.storyboard in Resources */, 135 | DDADE3DC1F999D220030577E /* monster.png in Resources */, 136 | DDADE3DD1F999D250030577E /* ball.png in Resources */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXResourcesBuildPhase section */ 141 | 142 | /* Begin PBXSourcesBuildPhase section */ 143 | DDADE3C11F999C340030577E /* Sources */ = { 144 | isa = PBXSourcesBuildPhase; 145 | buildActionMask = 2147483647; 146 | files = ( 147 | DDADE3CB1F999C340030577E /* ViewController.swift in Sources */, 148 | DDADE3C91F999C340030577E /* AppDelegate.swift in Sources */, 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXSourcesBuildPhase section */ 153 | 154 | /* Begin PBXVariantGroup section */ 155 | DDADE3CC1F999C340030577E /* Main.storyboard */ = { 156 | isa = PBXVariantGroup; 157 | children = ( 158 | DDADE3CD1F999C340030577E /* Base */, 159 | ); 160 | name = Main.storyboard; 161 | sourceTree = ""; 162 | }; 163 | DDADE3D11F999C340030577E /* LaunchScreen.storyboard */ = { 164 | isa = PBXVariantGroup; 165 | children = ( 166 | DDADE3D21F999C340030577E /* Base */, 167 | ); 168 | name = LaunchScreen.storyboard; 169 | sourceTree = ""; 170 | }; 171 | /* End PBXVariantGroup section */ 172 | 173 | /* Begin XCBuildConfiguration section */ 174 | DDADE3D51F999C340030577E /* Debug */ = { 175 | isa = XCBuildConfiguration; 176 | buildSettings = { 177 | ALWAYS_SEARCH_USER_PATHS = NO; 178 | CLANG_ANALYZER_NONNULL = YES; 179 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 181 | CLANG_CXX_LIBRARY = "libc++"; 182 | CLANG_ENABLE_MODULES = YES; 183 | CLANG_ENABLE_OBJC_ARC = YES; 184 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 185 | CLANG_WARN_BOOL_CONVERSION = YES; 186 | CLANG_WARN_COMMA = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 189 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 190 | CLANG_WARN_EMPTY_BODY = YES; 191 | CLANG_WARN_ENUM_CONVERSION = YES; 192 | CLANG_WARN_INFINITE_RECURSION = YES; 193 | CLANG_WARN_INT_CONVERSION = YES; 194 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 195 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 196 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 197 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 198 | CLANG_WARN_STRICT_PROTOTYPES = YES; 199 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 200 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 201 | CLANG_WARN_UNREACHABLE_CODE = YES; 202 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 203 | CODE_SIGN_IDENTITY = "iPhone Developer"; 204 | COPY_PHASE_STRIP = NO; 205 | DEBUG_INFORMATION_FORMAT = dwarf; 206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 207 | ENABLE_TESTABILITY = YES; 208 | GCC_C_LANGUAGE_STANDARD = gnu11; 209 | GCC_DYNAMIC_NO_PIC = NO; 210 | GCC_NO_COMMON_BLOCKS = YES; 211 | GCC_OPTIMIZATION_LEVEL = 0; 212 | GCC_PREPROCESSOR_DEFINITIONS = ( 213 | "DEBUG=1", 214 | "$(inherited)", 215 | ); 216 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 217 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 218 | GCC_WARN_UNDECLARED_SELECTOR = YES; 219 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 220 | GCC_WARN_UNUSED_FUNCTION = YES; 221 | GCC_WARN_UNUSED_VARIABLE = YES; 222 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 223 | MTL_ENABLE_DEBUG_INFO = YES; 224 | ONLY_ACTIVE_ARCH = YES; 225 | SDKROOT = iphoneos; 226 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 227 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 228 | }; 229 | name = Debug; 230 | }; 231 | DDADE3D61F999C340030577E /* Release */ = { 232 | isa = XCBuildConfiguration; 233 | buildSettings = { 234 | ALWAYS_SEARCH_USER_PATHS = NO; 235 | CLANG_ANALYZER_NONNULL = YES; 236 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 238 | CLANG_CXX_LIBRARY = "libc++"; 239 | CLANG_ENABLE_MODULES = YES; 240 | CLANG_ENABLE_OBJC_ARC = YES; 241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_COMMA = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 246 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 247 | CLANG_WARN_EMPTY_BODY = YES; 248 | CLANG_WARN_ENUM_CONVERSION = YES; 249 | CLANG_WARN_INFINITE_RECURSION = YES; 250 | CLANG_WARN_INT_CONVERSION = YES; 251 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 253 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 254 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 255 | CLANG_WARN_STRICT_PROTOTYPES = YES; 256 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 257 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | CODE_SIGN_IDENTITY = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 263 | ENABLE_NS_ASSERTIONS = NO; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu11; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 274 | MTL_ENABLE_DEBUG_INFO = NO; 275 | SDKROOT = iphoneos; 276 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 277 | VALIDATE_PRODUCT = YES; 278 | }; 279 | name = Release; 280 | }; 281 | DDADE3D81F999C340030577E /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | CODE_SIGN_STYLE = Automatic; 286 | DEVELOPMENT_TEAM = BCEFQF8MNF; 287 | INFOPLIST_FILE = "SpriteKit Standalone/Info.plist"; 288 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 289 | PRODUCT_BUNDLE_IDENTIFIER = "io.justinmiller.SpriteKit-Standalone"; 290 | PRODUCT_NAME = "$(TARGET_NAME)"; 291 | SWIFT_VERSION = 4.0; 292 | TARGETED_DEVICE_FAMILY = "1,2"; 293 | }; 294 | name = Debug; 295 | }; 296 | DDADE3D91F999C340030577E /* Release */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CODE_SIGN_STYLE = Automatic; 301 | DEVELOPMENT_TEAM = BCEFQF8MNF; 302 | INFOPLIST_FILE = "SpriteKit Standalone/Info.plist"; 303 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 304 | PRODUCT_BUNDLE_IDENTIFIER = "io.justinmiller.SpriteKit-Standalone"; 305 | PRODUCT_NAME = "$(TARGET_NAME)"; 306 | SWIFT_VERSION = 4.0; 307 | TARGETED_DEVICE_FAMILY = "1,2"; 308 | }; 309 | name = Release; 310 | }; 311 | /* End XCBuildConfiguration section */ 312 | 313 | /* Begin XCConfigurationList section */ 314 | DDADE3C01F999C330030577E /* Build configuration list for PBXProject "SpriteKit Standalone" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | DDADE3D51F999C340030577E /* Debug */, 318 | DDADE3D61F999C340030577E /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | defaultConfigurationName = Release; 322 | }; 323 | DDADE3D71F999C340030577E /* Build configuration list for PBXNativeTarget "SpriteKit Standalone" */ = { 324 | isa = XCConfigurationList; 325 | buildConfigurations = ( 326 | DDADE3D81F999C340030577E /* Debug */, 327 | DDADE3D91F999C340030577E /* Release */, 328 | ); 329 | defaultConfigurationIsVisible = 0; 330 | defaultConfigurationName = Release; 331 | }; 332 | /* End XCConfigurationList section */ 333 | }; 334 | rootObject = DDADE3BD1F999C330030577E /* Project object */; 335 | } 336 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { 4 | 5 | var window: UIWindow? 6 | 7 | } 8 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | SpriteKit Demo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SpriteKit 3 | 4 | class ViewController: UIViewController { 5 | 6 | var spriteView: SKView! 7 | var monster: SKNode! 8 | var ball: SKNode! 9 | 10 | override func viewDidLoad() { 11 | super.viewDidLoad() 12 | setupSprites() 13 | } 14 | 15 | func setupSprites() { 16 | spriteView = SKView() 17 | spriteView.frame = view.bounds 18 | view.addSubview(spriteView) 19 | 20 | let scene = SKScene(size: spriteView.bounds.size) 21 | scene.backgroundColor = .white 22 | scene.anchorPoint = CGPoint(x: 0.5, y: 0.5) 23 | spriteView.presentScene(scene) 24 | 25 | spriteView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))) 26 | 27 | monster = SKSpriteNode(imageNamed: "monster.png") 28 | monster.position = CGPoint(x: 0, y: 0) 29 | monster.setScale(0.5) 30 | scene.addChild(monster) 31 | 32 | ball = SKSpriteNode(imageNamed: "ball.png") 33 | ball.position = CGPoint(x: 250, y: 70) 34 | ball.setScale(0.75) 35 | scene.addChild(ball) 36 | 37 | ball.physicsBody = SKPhysicsBody(circleOfRadius: 38 | max(ball.frame.size.width, ball.frame.size.height) / 2) 39 | ball.physicsBody!.affectedByGravity = true 40 | ball.physicsBody!.usesPreciseCollisionDetection = true 41 | ball.physicsBody!.restitution = 0.75 42 | ball.physicsBody!.isDynamic = false 43 | 44 | let floor = SKSpriteNode() 45 | floor.size = CGSize(width: 5000, height: 1) 46 | floor.position = CGPoint(x: ball.position.x - 500, y: ball.position.y - 350) 47 | spriteView.scene!.addChild(floor) 48 | 49 | floor.physicsBody = SKPhysicsBody(rectangleOf: floor.size) 50 | floor.physicsBody!.isDynamic = false 51 | } 52 | 53 | @objc func handleTap(_ tap: UITapGestureRecognizer) { 54 | let spin = SKAction.applyAngularImpulse(-0.1, duration: 0.5) 55 | ball.run(spin) 56 | ball.physicsBody!.isDynamic = true 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/SpriteKit Standalone/SpriteKit Standalone/ball.png -------------------------------------------------------------------------------- /code/SpriteKit Standalone/SpriteKit Standalone/monster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/SpriteKit Standalone/SpriteKit Standalone/monster.png -------------------------------------------------------------------------------- /code/SpriteKit Standalone/readme.md: -------------------------------------------------------------------------------- 1 | # SpriteKit Standalone 2 | 3 | The app displays two sprites, a monster and a ball. When you tap the screen, the monster drops the ball, which bounces and rolls, then comes to a stop. 4 | 5 | Note the invisible floor node which interacts with the physics environment. 6 | 7 | ![](screenshot.png) 8 | -------------------------------------------------------------------------------- /code/SpriteKit Standalone/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/code/SpriteKit Standalone/screenshot.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # SpriteKit, SceneKit, ARKit—Oh My! 2 | 3 | Intro to SpriteKit (2D scenes), SceneKit (3D scenes), and ARKit (augmented reality, which can use either of those kits for rendered content). 4 | 5 | The talk featured a number of iPad and iPhone screen capture videos rather than jumping out to a real device. They are labeled in the slide notes in alphabetical order. 6 | 7 | * _[Swift by Northwest session page](https://swiftbynorthwest.com/spritekit-scenekit-arkit-oh-my-justin-miller)_ 8 | * _[Portland CocoaHeads meetup page](https://www.meetup.com/PDX-iOS-CocoaHeads/events/246978613/)_ 9 | 10 | ![slides.pdf](title.png) 11 | -------------------------------------------------------------------------------- /slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/slides.pdf -------------------------------------------------------------------------------- /title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/title.png -------------------------------------------------------------------------------- /videos/Video A.MOV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video A.MOV -------------------------------------------------------------------------------- /videos/Video B.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video B.MP4 -------------------------------------------------------------------------------- /videos/Video C.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video C.mov -------------------------------------------------------------------------------- /videos/Video D.MOV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video D.MOV -------------------------------------------------------------------------------- /videos/Video E.MOV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video E.MOV -------------------------------------------------------------------------------- /videos/Video F.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video F.MP4 -------------------------------------------------------------------------------- /videos/Video G.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video G.MP4 -------------------------------------------------------------------------------- /videos/Video H.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video H.mp4 -------------------------------------------------------------------------------- /videos/Video I.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video I.mp4 -------------------------------------------------------------------------------- /videos/Video J.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video J.mp4 -------------------------------------------------------------------------------- /videos/Video K.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video K.mov -------------------------------------------------------------------------------- /videos/Video L.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/incanus/SpriteKitSceneKitARKit/d97d46b79726a8772a51c9d743872327775f8df7/videos/Video L.mov --------------------------------------------------------------------------------