├── .gitignore ├── ARKitImageDetectionTutorial.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── ARKitImageDetectionTutorial ├── AnimationInfo.swift ├── AppDelegate.swift ├── Assets.xcassets │ ├── AR Resources.arresourcegroup │ │ ├── Contents.json │ │ └── PlaneAnchor.arreferenceimage │ │ │ ├── 1234-01-1.png │ │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x-2.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── iTunesArtwork@2x.png │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.swift └── art.scnassets │ └── plane.scn ├── PlaneAnchor.pdf └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Build generated 2 | build/ 3 | DerivedData/ 4 | 5 | ## Various settings 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | 16 | ## Other 17 | *.moved-aside 18 | *.xccheckout 19 | *.xcscmblueprint 20 | 21 | ## Obj-C/Swift specific 22 | *.hmap 23 | *.ipa 24 | *.dSYM.zip 25 | *.dSYM 26 | 27 | ## Playgrounds 28 | timeline.xctimeline 29 | playground.xcworkspace 30 | 31 | # Swift Package Manager 32 | # 33 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 34 | # Packages/ 35 | # Package.pins 36 | # Package.resolved 37 | .build/ 38 | 39 | # CocoaPods 40 | # 41 | # We recommend against adding the Pods directory to your .gitignore. However 42 | # you should judge for yourself, the pros and cons are mentioned at: 43 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 44 | # 45 | # Pods/ 46 | 47 | # Carthage 48 | # 49 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 50 | # Carthage/Checkouts 51 | 52 | Carthage/Build 53 | 54 | # fastlane 55 | # 56 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 57 | # screenshots whenever they are needed. 58 | # For more information about the recommended setup visit: 59 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 60 | 61 | fastlane/report.xml 62 | fastlane/Preview.html 63 | fastlane/screenshots/**/*.png 64 | fastlane/test_output 65 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E49C2DFF20BC53F700D6C6F3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49C2DFE20BC53F700D6C6F3 /* AppDelegate.swift */; }; 11 | E49C2E0120BC53F700D6C6F3 /* art.scnassets in Resources */ = {isa = PBXBuildFile; fileRef = E49C2E0020BC53F700D6C6F3 /* art.scnassets */; }; 12 | E49C2E0320BC53F700D6C6F3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49C2E0220BC53F700D6C6F3 /* ViewController.swift */; }; 13 | E49C2E0620BC53F700D6C6F3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E49C2E0420BC53F700D6C6F3 /* Main.storyboard */; }; 14 | E49C2E0820BC53F800D6C6F3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E49C2E0720BC53F800D6C6F3 /* Assets.xcassets */; }; 15 | E49C2E0B20BC53F800D6C6F3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E49C2E0920BC53F800D6C6F3 /* LaunchScreen.storyboard */; }; 16 | E4CBE4C720C58002004450ED /* AnimationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4CBE4C620C58002004450ED /* AnimationInfo.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | E49C2DFB20BC53F700D6C6F3 /* ARKitImageDetectionTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ARKitImageDetectionTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | E49C2DFE20BC53F700D6C6F3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | E49C2E0020BC53F700D6C6F3 /* art.scnassets */ = {isa = PBXFileReference; lastKnownFileType = wrapper.scnassets; path = art.scnassets; sourceTree = ""; }; 23 | E49C2E0220BC53F700D6C6F3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 24 | E49C2E0520BC53F700D6C6F3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 25 | E49C2E0720BC53F800D6C6F3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | E49C2E0A20BC53F800D6C6F3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 27 | E49C2E0C20BC53F800D6C6F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | E4CBE4C620C58002004450ED /* AnimationInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationInfo.swift; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | E49C2DF820BC53F700D6C6F3 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | E49C2DF220BC53F700D6C6F3 = { 43 | isa = PBXGroup; 44 | children = ( 45 | E49C2DFD20BC53F700D6C6F3 /* ARKitImageDetectionTutorial */, 46 | E49C2DFC20BC53F700D6C6F3 /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | E49C2DFC20BC53F700D6C6F3 /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | E49C2DFB20BC53F700D6C6F3 /* ARKitImageDetectionTutorial.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | E49C2DFD20BC53F700D6C6F3 /* ARKitImageDetectionTutorial */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | E49C2E0C20BC53F800D6C6F3 /* Info.plist */, 62 | E49C2E0020BC53F700D6C6F3 /* art.scnassets */, 63 | E4CBE4C620C58002004450ED /* AnimationInfo.swift */, 64 | E49C2DFE20BC53F700D6C6F3 /* AppDelegate.swift */, 65 | E49C2E0220BC53F700D6C6F3 /* ViewController.swift */, 66 | E49C2E0720BC53F800D6C6F3 /* Assets.xcassets */, 67 | E49C2E0920BC53F800D6C6F3 /* LaunchScreen.storyboard */, 68 | E49C2E0420BC53F700D6C6F3 /* Main.storyboard */, 69 | ); 70 | path = ARKitImageDetectionTutorial; 71 | sourceTree = ""; 72 | }; 73 | /* End PBXGroup section */ 74 | 75 | /* Begin PBXNativeTarget section */ 76 | E49C2DFA20BC53F700D6C6F3 /* ARKitImageDetectionTutorial */ = { 77 | isa = PBXNativeTarget; 78 | buildConfigurationList = E49C2E0F20BC53F800D6C6F3 /* Build configuration list for PBXNativeTarget "ARKitImageDetectionTutorial" */; 79 | buildPhases = ( 80 | E49C2DF720BC53F700D6C6F3 /* Sources */, 81 | E49C2DF820BC53F700D6C6F3 /* Frameworks */, 82 | E49C2DF920BC53F700D6C6F3 /* Resources */, 83 | ); 84 | buildRules = ( 85 | ); 86 | dependencies = ( 87 | ); 88 | name = ARKitImageDetectionTutorial; 89 | productName = ARKitImageDetectionTutorial; 90 | productReference = E49C2DFB20BC53F700D6C6F3 /* ARKitImageDetectionTutorial.app */; 91 | productType = "com.apple.product-type.application"; 92 | }; 93 | /* End PBXNativeTarget section */ 94 | 95 | /* Begin PBXProject section */ 96 | E49C2DF320BC53F700D6C6F3 /* Project object */ = { 97 | isa = PBXProject; 98 | attributes = { 99 | LastSwiftUpdateCheck = 0930; 100 | LastUpgradeCheck = 0930; 101 | ORGANIZATIONNAME = "Ivan Nesterenko"; 102 | TargetAttributes = { 103 | E49C2DFA20BC53F700D6C6F3 = { 104 | CreatedOnToolsVersion = 9.3.1; 105 | }; 106 | }; 107 | }; 108 | buildConfigurationList = E49C2DF620BC53F700D6C6F3 /* Build configuration list for PBXProject "ARKitImageDetectionTutorial" */; 109 | compatibilityVersion = "Xcode 9.3"; 110 | developmentRegion = en; 111 | hasScannedForEncodings = 0; 112 | knownRegions = ( 113 | en, 114 | Base, 115 | ); 116 | mainGroup = E49C2DF220BC53F700D6C6F3; 117 | productRefGroup = E49C2DFC20BC53F700D6C6F3 /* Products */; 118 | projectDirPath = ""; 119 | projectRoot = ""; 120 | targets = ( 121 | E49C2DFA20BC53F700D6C6F3 /* ARKitImageDetectionTutorial */, 122 | ); 123 | }; 124 | /* End PBXProject section */ 125 | 126 | /* Begin PBXResourcesBuildPhase section */ 127 | E49C2DF920BC53F700D6C6F3 /* Resources */ = { 128 | isa = PBXResourcesBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | E49C2E0120BC53F700D6C6F3 /* art.scnassets in Resources */, 132 | E49C2E0B20BC53F800D6C6F3 /* LaunchScreen.storyboard in Resources */, 133 | E49C2E0820BC53F800D6C6F3 /* Assets.xcassets in Resources */, 134 | E49C2E0620BC53F700D6C6F3 /* Main.storyboard in Resources */, 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXResourcesBuildPhase section */ 139 | 140 | /* Begin PBXSourcesBuildPhase section */ 141 | E49C2DF720BC53F700D6C6F3 /* Sources */ = { 142 | isa = PBXSourcesBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | E4CBE4C720C58002004450ED /* AnimationInfo.swift in Sources */, 146 | E49C2E0320BC53F700D6C6F3 /* ViewController.swift in Sources */, 147 | E49C2DFF20BC53F700D6C6F3 /* AppDelegate.swift in Sources */, 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | /* End PBXSourcesBuildPhase section */ 152 | 153 | /* Begin PBXVariantGroup section */ 154 | E49C2E0420BC53F700D6C6F3 /* Main.storyboard */ = { 155 | isa = PBXVariantGroup; 156 | children = ( 157 | E49C2E0520BC53F700D6C6F3 /* Base */, 158 | ); 159 | name = Main.storyboard; 160 | sourceTree = ""; 161 | }; 162 | E49C2E0920BC53F800D6C6F3 /* LaunchScreen.storyboard */ = { 163 | isa = PBXVariantGroup; 164 | children = ( 165 | E49C2E0A20BC53F800D6C6F3 /* Base */, 166 | ); 167 | name = LaunchScreen.storyboard; 168 | sourceTree = ""; 169 | }; 170 | /* End PBXVariantGroup section */ 171 | 172 | /* Begin XCBuildConfiguration section */ 173 | E49C2E0D20BC53F800D6C6F3 /* Debug */ = { 174 | isa = XCBuildConfiguration; 175 | buildSettings = { 176 | ALWAYS_SEARCH_USER_PATHS = NO; 177 | CLANG_ANALYZER_NONNULL = YES; 178 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 179 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 180 | CLANG_CXX_LIBRARY = "libc++"; 181 | CLANG_ENABLE_MODULES = YES; 182 | CLANG_ENABLE_OBJC_ARC = YES; 183 | CLANG_ENABLE_OBJC_WEAK = 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 189 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 190 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 191 | CLANG_WARN_EMPTY_BODY = YES; 192 | CLANG_WARN_ENUM_CONVERSION = YES; 193 | CLANG_WARN_INFINITE_RECURSION = YES; 194 | CLANG_WARN_INT_CONVERSION = YES; 195 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 196 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 197 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 199 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 200 | CLANG_WARN_STRICT_PROTOTYPES = YES; 201 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 202 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 203 | CLANG_WARN_UNREACHABLE_CODE = YES; 204 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 205 | CODE_SIGN_IDENTITY = "iPhone Developer"; 206 | COPY_PHASE_STRIP = NO; 207 | DEBUG_INFORMATION_FORMAT = dwarf; 208 | ENABLE_STRICT_OBJC_MSGSEND = YES; 209 | ENABLE_TESTABILITY = YES; 210 | GCC_C_LANGUAGE_STANDARD = gnu11; 211 | GCC_DYNAMIC_NO_PIC = NO; 212 | GCC_NO_COMMON_BLOCKS = YES; 213 | GCC_OPTIMIZATION_LEVEL = 0; 214 | GCC_PREPROCESSOR_DEFINITIONS = ( 215 | "DEBUG=1", 216 | "$(inherited)", 217 | ); 218 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 219 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 220 | GCC_WARN_UNDECLARED_SELECTOR = YES; 221 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 222 | GCC_WARN_UNUSED_FUNCTION = YES; 223 | GCC_WARN_UNUSED_VARIABLE = YES; 224 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 225 | MTL_ENABLE_DEBUG_INFO = YES; 226 | ONLY_ACTIVE_ARCH = YES; 227 | SDKROOT = iphoneos; 228 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 229 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 230 | }; 231 | name = Debug; 232 | }; 233 | E49C2E0E20BC53F800D6C6F3 /* Release */ = { 234 | isa = XCBuildConfiguration; 235 | buildSettings = { 236 | ALWAYS_SEARCH_USER_PATHS = NO; 237 | CLANG_ANALYZER_NONNULL = YES; 238 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_ENABLE_OBJC_WEAK = YES; 244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 245 | CLANG_WARN_BOOL_CONVERSION = YES; 246 | CLANG_WARN_COMMA = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 250 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 251 | CLANG_WARN_EMPTY_BODY = YES; 252 | CLANG_WARN_ENUM_CONVERSION = YES; 253 | CLANG_WARN_INFINITE_RECURSION = YES; 254 | CLANG_WARN_INT_CONVERSION = YES; 255 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 257 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 259 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 260 | CLANG_WARN_STRICT_PROTOTYPES = YES; 261 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 262 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 263 | CLANG_WARN_UNREACHABLE_CODE = YES; 264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 265 | CODE_SIGN_IDENTITY = "iPhone Developer"; 266 | COPY_PHASE_STRIP = NO; 267 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 268 | ENABLE_NS_ASSERTIONS = NO; 269 | ENABLE_STRICT_OBJC_MSGSEND = YES; 270 | GCC_C_LANGUAGE_STANDARD = gnu11; 271 | GCC_NO_COMMON_BLOCKS = YES; 272 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 273 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 274 | GCC_WARN_UNDECLARED_SELECTOR = YES; 275 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 276 | GCC_WARN_UNUSED_FUNCTION = YES; 277 | GCC_WARN_UNUSED_VARIABLE = YES; 278 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 279 | MTL_ENABLE_DEBUG_INFO = NO; 280 | SDKROOT = iphoneos; 281 | SWIFT_COMPILATION_MODE = wholemodule; 282 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 283 | VALIDATE_PRODUCT = YES; 284 | }; 285 | name = Release; 286 | }; 287 | E49C2E1020BC53F800D6C6F3 /* Debug */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 291 | CODE_SIGN_STYLE = Automatic; 292 | DEVELOPMENT_TEAM = ""; 293 | INFOPLIST_FILE = ARKitImageDetectionTutorial/Info.plist; 294 | IPHONEOS_DEPLOYMENT_TARGET = 12; 295 | LD_RUNPATH_SEARCH_PATHS = ( 296 | "$(inherited)", 297 | "@executable_path/Frameworks", 298 | ); 299 | PRODUCT_BUNDLE_IDENTIFIER = ARKitImageDetectionTutorial; 300 | PRODUCT_NAME = "$(TARGET_NAME)"; 301 | SWIFT_VERSION = 4.0; 302 | TARGETED_DEVICE_FAMILY = "1,2"; 303 | }; 304 | name = Debug; 305 | }; 306 | E49C2E1120BC53F800D6C6F3 /* Release */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 310 | CODE_SIGN_STYLE = Automatic; 311 | DEVELOPMENT_TEAM = ""; 312 | INFOPLIST_FILE = ARKitImageDetectionTutorial/Info.plist; 313 | IPHONEOS_DEPLOYMENT_TARGET = 12; 314 | LD_RUNPATH_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "@executable_path/Frameworks", 317 | ); 318 | PRODUCT_BUNDLE_IDENTIFIER = ARKitImageDetectionTutorial; 319 | PRODUCT_NAME = "$(TARGET_NAME)"; 320 | SWIFT_VERSION = 4.0; 321 | TARGETED_DEVICE_FAMILY = "1,2"; 322 | }; 323 | name = Release; 324 | }; 325 | /* End XCBuildConfiguration section */ 326 | 327 | /* Begin XCConfigurationList section */ 328 | E49C2DF620BC53F700D6C6F3 /* Build configuration list for PBXProject "ARKitImageDetectionTutorial" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | E49C2E0D20BC53F800D6C6F3 /* Debug */, 332 | E49C2E0E20BC53F800D6C6F3 /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | E49C2E0F20BC53F800D6C6F3 /* Build configuration list for PBXNativeTarget "ARKitImageDetectionTutorial" */ = { 338 | isa = XCConfigurationList; 339 | buildConfigurations = ( 340 | E49C2E1020BC53F800D6C6F3 /* Debug */, 341 | E49C2E1120BC53F800D6C6F3 /* Release */, 342 | ); 343 | defaultConfigurationIsVisible = 0; 344 | defaultConfigurationName = Release; 345 | }; 346 | /* End XCConfigurationList section */ 347 | }; 348 | rootObject = E49C2DF320BC53F700D6C6F3 /* Project object */; 349 | } 350 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/AnimationInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimationInfo.swift 3 | // ARKitImageDetectionTutorial 4 | // 5 | // Created by Ivan Nesterenko on 4/6/18. 6 | // Copyright © 2018 Ivan Nesterenko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SceneKit 11 | 12 | struct AnimationInfo { 13 | var startTime: TimeInterval 14 | var duration: TimeInterval 15 | var initialModelPosition: simd_float3 16 | var finalModelPosition: simd_float3 17 | var initialModelOrientation: simd_quatf 18 | var finalModelOrientation: simd_quatf 19 | } 20 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ARKitImageDetectionTutorial 4 | // 5 | // Created by Ivan Nesterenko on 28/5/18. 6 | // Copyright © 2018 Ivan Nesterenko. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 17 | 18 | return true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AR Resources.arresourcegroup/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | }, 6 | "resources" : [ 7 | { 8 | "filename" : "PlaneAnchor.arreferenceimage" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AR Resources.arresourcegroup/PlaneAnchor.arreferenceimage/1234-01-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AR Resources.arresourcegroup/PlaneAnchor.arreferenceimage/1234-01-1.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AR Resources.arresourcegroup/PlaneAnchor.arreferenceimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "1234-01-1.png" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "width" : 21, 14 | "unit" : "centimeters" 15 | } 16 | } -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-2.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "iTunesArtwork@2x.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-2.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/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 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/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 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Image Detection Tutorial 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 | NSCameraUsageDescription 26 | This application will use the camera for Augmented Reality. 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | arkit 35 | 36 | UIStatusBarHidden 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ARKitImageDetectionTutorial 4 | // 5 | // Created by Ivan Nesterenko on 28/5/18. 6 | // Copyright © 2018 Ivan Nesterenko. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SceneKit 11 | import ARKit 12 | 13 | class ViewController: UIViewController, ARSCNViewDelegate { 14 | 15 | @IBOutlet var sceneView: ARSCNView! 16 | private var planeNode: SCNNode? 17 | private var imageNode: SCNNode? 18 | private var animationInfo: AnimationInfo? 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | let scene = SCNScene() 24 | sceneView.scene = scene 25 | sceneView.delegate = self 26 | } 27 | 28 | override func viewWillAppear(_ animated: Bool) { 29 | super.viewWillAppear(animated) 30 | 31 | // Load reference images to look for from "AR Resources" folder 32 | guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else { 33 | fatalError("Missing expected asset catalog resources.") 34 | } 35 | 36 | // Create a session configuration 37 | let configuration = ARWorldTrackingConfiguration() 38 | 39 | // Add previously loaded images to ARScene configuration as detectionImages 40 | configuration.detectionImages = referenceImages 41 | 42 | // Run the view's session 43 | sceneView.session.run(configuration) 44 | } 45 | 46 | func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { 47 | guard let imageAnchor = anchor as? ARImageAnchor else { 48 | return 49 | } 50 | 51 | // 1. Load plane's scene. 52 | let planeScene = SCNScene(named: "art.scnassets/plane.scn")! 53 | let planeNode = planeScene.rootNode.childNode(withName: "planeRootNode", recursively: true)! 54 | 55 | // 2. Calculate size based on planeNode's bounding box. 56 | let (min, max) = planeNode.boundingBox 57 | let size = SCNVector3Make(max.x - min.x, max.y - min.y, max.z - min.z) 58 | 59 | // 3. Calculate the ratio of difference between real image and object size. 60 | // Ignore Y axis because it will be pointed out of the image. 61 | let widthRatio = Float(imageAnchor.referenceImage.physicalSize.width)/size.x 62 | let heightRatio = Float(imageAnchor.referenceImage.physicalSize.height)/size.z 63 | // Pick smallest value to be sure that object fits into the image. 64 | let finalRatio = [widthRatio, heightRatio].min()! 65 | 66 | // 4. Set transform from imageAnchor data. 67 | planeNode.transform = SCNMatrix4(imageAnchor.transform) 68 | 69 | // 5. Animate appearance by scaling model from 0 to previously calculated value. 70 | let appearanceAction = SCNAction.scale(to: CGFloat(finalRatio), duration: 0.4) 71 | appearanceAction.timingMode = .easeOut 72 | // Set initial scale to 0. 73 | planeNode.scale = SCNVector3Make(0.001, 0.001, 0.001) 74 | // Add to root node. 75 | sceneView.scene.rootNode.addChildNode(planeNode) 76 | // Run the appearance animation. 77 | planeNode.runAction(appearanceAction) 78 | 79 | self.planeNode = planeNode 80 | self.imageNode = node 81 | } 82 | 83 | func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { 84 | guard let imageNode = imageNode, let planeNode = planeNode else { 85 | return 86 | } 87 | 88 | // 1. Unwrap animationInfo. Calculate animationInfo if it is nil. 89 | guard let animationInfo = animationInfo else { 90 | refreshAnimationVariables(startTime: time, 91 | initialPosition: planeNode.simdWorldPosition, 92 | finalPosition: imageNode.simdWorldPosition, 93 | initialOrientation: planeNode.simdWorldOrientation, 94 | finalOrientation: imageNode.simdWorldOrientation) 95 | return 96 | } 97 | 98 | // 2. Calculate new animationInfo if image position or orientation changed. 99 | if !simd_equal(animationInfo.finalModelPosition, imageNode.simdWorldPosition) || animationInfo.finalModelOrientation != imageNode.simdWorldOrientation { 100 | 101 | refreshAnimationVariables(startTime: time, 102 | initialPosition: planeNode.simdWorldPosition, 103 | finalPosition: imageNode.simdWorldPosition, 104 | initialOrientation: planeNode.simdWorldOrientation, 105 | finalOrientation: imageNode.simdWorldOrientation) 106 | } 107 | 108 | // 3. Calculate interpolation based on passedTime/totalTime ratio. 109 | let passedTime = time - animationInfo.startTime 110 | var t = min(Float(passedTime/animationInfo.duration), 1) 111 | // Applying curve function to time parameter to achieve "ease out" timing 112 | t = sin(t * .pi * 0.5) 113 | 114 | // 4. Calculate and set new model position and orientation. 115 | let f3t = simd_make_float3(t, t, t) 116 | planeNode.simdWorldPosition = simd_mix(animationInfo.initialModelPosition, animationInfo.finalModelPosition, f3t) 117 | planeNode.simdWorldOrientation = simd_slerp(animationInfo.initialModelOrientation, animationInfo.finalModelOrientation, t) 118 | //planeNode.simdWorldOrientation = imageNode.simdWorldOrientation 119 | } 120 | 121 | func refreshAnimationVariables(startTime: TimeInterval, initialPosition: float3, finalPosition: float3, initialOrientation: simd_quatf, finalOrientation: simd_quatf) { 122 | let distance = simd_distance(initialPosition, finalPosition) 123 | // Average speed of movement is 0.15 m/s. 124 | let speed = Float(0.15) 125 | // Total time is calculated as distance/speed. Min time is set to 0.1s and max is set to 2s. 126 | let animationDuration = Double(min(max(0.1, distance/speed), 2)) 127 | // Store animation information for later usage. 128 | animationInfo = AnimationInfo(startTime: startTime, 129 | duration: animationDuration, 130 | initialModelPosition: initialPosition, 131 | finalModelPosition: finalPosition, 132 | initialModelOrientation: initialOrientation, 133 | finalModelOrientation: finalOrientation) 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /ARKitImageDetectionTutorial/art.scnassets/plane.scn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/ARKitImageDetectionTutorial/art.scnassets/plane.scn -------------------------------------------------------------------------------- /PlaneAnchor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krootl/ARKitImageDetectionTutorial/319001b5a1ed99765713934bab75870e761f24d4/PlaneAnchor.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARKitImageDetectionTutorial 2 | ARKit image detection tutorial code for [Medium article](https://medium.com/@ivannesterenko/arkit-tutorial-image-recognition-and-virtual-content-transform-91484ceaf5d5). 3 | 4 |

5 | 6 |

7 | 8 | In this tutorial, it's described how to use image recognition in ARKit, place virtual content on top of a recognized image and work with scale. Also, you will learn how to animate changes of the heading and position based on the image's transform with lerp. Principal difference with ARKit 2.0 image tracking is that you can still use plane detection. 9 | You can also find .pdf file of the image anchor that is used in the tutorial in this repo. 10 | --------------------------------------------------------------------------------