From 840c14d5836f1c33564574b3e6e073e397593db1 Mon Sep 17 00:00:00 2001 From: Marius Horga Date: Sat, 29 Jul 2017 00:17:49 -0500 Subject: [PATCH] added arkit metal --- ARKit/arkitdemo.xcodeproj/project.pbxproj | 309 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 10421 bytes .../UserInterfaceState.xcuserstate | Bin 0 -> 23527 bytes .../xcschemes/xcschememanagement.plist | 14 + .../xcschemes/xcschememanagement.plist | 14 + ARKit/arkitdemo/AppDelegate.swift | 7 + ARKit/arkitdemo/Base.lproj/Main.storyboard | 25 ++ ARKit/arkitdemo/Info.plist | 47 +++ ARKit/arkitdemo/Renderer.swift | 298 +++++++++++++++++ ARKit/arkitdemo/Shaders.metal | 100 ++++++ ARKit/arkitdemo/ViewController.swift | 61 ++++ README.md | 1 + 13 files changed, 883 insertions(+) create mode 100644 ARKit/arkitdemo.xcodeproj/project.pbxproj create mode 100644 ARKit/arkitdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ARKit/arkitdemo.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ARKit/arkitdemo.xcodeproj/project.xcworkspace/xcuserdata/mhorga.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ARKit/arkitdemo.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ARKit/arkitdemo.xcodeproj/xcuserdata/mhorga.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ARKit/arkitdemo/AppDelegate.swift create mode 100644 ARKit/arkitdemo/Base.lproj/Main.storyboard create mode 100644 ARKit/arkitdemo/Info.plist create mode 100644 ARKit/arkitdemo/Renderer.swift create mode 100644 ARKit/arkitdemo/Shaders.metal create mode 100644 ARKit/arkitdemo/ViewController.swift diff --git a/ARKit/arkitdemo.xcodeproj/project.pbxproj b/ARKit/arkitdemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..769acc8 --- /dev/null +++ b/ARKit/arkitdemo.xcodeproj/project.pbxproj @@ -0,0 +1,309 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 3C335AC71F27D12500FF39A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C335AC61F27D12500FF39A5 /* AppDelegate.swift */; }; + 3C335AC91F27D12500FF39A5 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 3C335AC81F27D12500FF39A5 /* Shaders.metal */; }; + 3C335ACC1F27D12500FF39A5 /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C335ACB1F27D12500FF39A5 /* Renderer.swift */; }; + 3C335ACE1F27D12500FF39A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C335ACD1F27D12500FF39A5 /* ViewController.swift */; }; + 3C335AD11F27D12500FF39A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3C335ACF1F27D12500FF39A5 /* Main.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3C335AC31F27D12500FF39A5 /* arkitdemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = arkitdemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C335AC61F27D12500FF39A5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 3C335AC81F27D12500FF39A5 /* Shaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; + 3C335ACB1F27D12500FF39A5 /* Renderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Renderer.swift; sourceTree = ""; }; + 3C335ACD1F27D12500FF39A5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 3C335AD01F27D12500FF39A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3C335AD71F27D12500FF39A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3C335AC01F27D12500FF39A5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3C335ABA1F27D12500FF39A5 = { + isa = PBXGroup; + children = ( + 3C335AC51F27D12500FF39A5 /* arkitdemo */, + 3C335AC41F27D12500FF39A5 /* Products */, + ); + sourceTree = ""; + }; + 3C335AC41F27D12500FF39A5 /* Products */ = { + isa = PBXGroup; + children = ( + 3C335AC31F27D12500FF39A5 /* arkitdemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 3C335AC51F27D12500FF39A5 /* arkitdemo */ = { + isa = PBXGroup; + children = ( + 3C335AC81F27D12500FF39A5 /* Shaders.metal */, + 3C335ACB1F27D12500FF39A5 /* Renderer.swift */, + 3C335ACD1F27D12500FF39A5 /* ViewController.swift */, + 3C335ACF1F27D12500FF39A5 /* Main.storyboard */, + 3C335AD71F27D12500FF39A5 /* Info.plist */, + 3C335AC61F27D12500FF39A5 /* AppDelegate.swift */, + ); + path = arkitdemo; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3C335AC21F27D12500FF39A5 /* arkitdemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3C335ADB1F27D12500FF39A5 /* Build configuration list for PBXNativeTarget "arkitdemo" */; + buildPhases = ( + 3C335ABF1F27D12500FF39A5 /* Sources */, + 3C335AC01F27D12500FF39A5 /* Frameworks */, + 3C335AC11F27D12500FF39A5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = arkitdemo; + productName = arkitdemo; + productReference = 3C335AC31F27D12500FF39A5 /* arkitdemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3C335ABB1F27D12500FF39A5 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0900; + LastUpgradeCheck = 0900; + ORGANIZATIONNAME = "Marius Horga"; + TargetAttributes = { + 3C335AC21F27D12500FF39A5 = { + CreatedOnToolsVersion = 9.0; + }; + }; + }; + buildConfigurationList = 3C335ABE1F27D12500FF39A5 /* Build configuration list for PBXProject "arkitdemo" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3C335ABA1F27D12500FF39A5; + productRefGroup = 3C335AC41F27D12500FF39A5 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3C335AC21F27D12500FF39A5 /* arkitdemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3C335AC11F27D12500FF39A5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C335AD11F27D12500FF39A5 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3C335ABF1F27D12500FF39A5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C335AC91F27D12500FF39A5 /* Shaders.metal in Sources */, + 3C335ACC1F27D12500FF39A5 /* Renderer.swift in Sources */, + 3C335ACE1F27D12500FF39A5 /* ViewController.swift in Sources */, + 3C335AC71F27D12500FF39A5 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3C335ACF1F27D12500FF39A5 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3C335AD01F27D12500FF39A5 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3C335AD91F27D12500FF39A5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 3C335ADA1F27D12500FF39A5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3C335ADC1F27D12500FF39A5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = C2X9Q6VFVJ; + INFOPLIST_FILE = arkitdemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.metalkit.arkitdemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3C335ADD1F27D12500FF39A5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = C2X9Q6VFVJ; + INFOPLIST_FILE = arkitdemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.metalkit.arkitdemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3C335ABE1F27D12500FF39A5 /* Build configuration list for PBXProject "arkitdemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3C335AD91F27D12500FF39A5 /* Debug */, + 3C335ADA1F27D12500FF39A5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3C335ADB1F27D12500FF39A5 /* Build configuration list for PBXNativeTarget "arkitdemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3C335ADC1F27D12500FF39A5 /* Debug */, + 3C335ADD1F27D12500FF39A5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3C335ABB1F27D12500FF39A5 /* Project object */; +} diff --git a/ARKit/arkitdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ARKit/arkitdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..0715532 --- /dev/null +++ b/ARKit/arkitdemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ARKit/arkitdemo.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ARKit/arkitdemo.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..42ae98ca6d59592e2eddc484d671dccbde2b7a73 GIT binary patch literal 10421 zcmd^Fd3;k<_P_T&mZV9W*X%D_leP#5U7;H&v~OR0LT>R7AyHK}1xXncsPNP1=k)<9vR9PV@OR$z9Gp_uO;7 z=X>r;b+g;$52U8PgD@h9L48nP)Q?GKQl=)(<$Zpa*E2QITRoev3HYZaI(;<_E@&=K z40xNB2;a7OCwm$7M-rq$YNSB}&^2fv8iWR;Ytaytf-+GS%0@Y8JSssGP$`;-CZWlw z3^gDZnvEKf8#N&h@}g!m2eqMF(cNezx(_{wHlU5D6Kz3D&{nh^J&Jasr_j^rIdlNM zfL=kbqqop;bON10@1xJq=jaRcCHfX4j4{Cs?t}Z{ez-rDU_Iur0UNOio3RDQVJo)b zcsu|P!D%=H=iuw{C_Dz|;{rSmPr#FKIj+D?T#ajRE#~nY?8AN>z%6(lUWjkTOYm~M z0^f!2#w+ptcpbV0KZrYV7v73@;K%T8ych4o`|(ToW&8?$10Thw@q73T{se!Dzro+) z@9+hJ2quIuqz~y!`Vl#aCMu#PCSoQQl1Q#4sU(wJM{-FKDIw*gf>e@O#6fN(4a7xe zlbgr_vXIBX5v5$p_>^a+Z8V&XJGFC*(`=75SP$3}y(!FnyT5Oh2YSBVnXW6eDBgOf;in zbc~*{GBzfjNnjG0K^2Lf7PtEtlADKONq?-J~+H#_ja`J5e-> zp@cG>h()oq4}F4GI@rX*w4%)H%$%&G%x3UZQ$<)md~7i8t77v&T= zSaoqh;S{g0(ckQ>;S0PqEls>95L#G^%qVdS(jh(KkO3KyiT0)aXn!i9QW~`dSx_9Z zA{#QH1S+G^G=?f@6lH0(gB{dc?i81&*4yeRwU_b!fY;}&cJuatGr$)(15O947lsB$ zlsl`(IDN(bN|)aSV;n5k)8+NLt9$j$3ilNGoJ}w^4jS@m0uVIe?SQy^uP5O1y4}3b z!HyE9gti*lSD2NPo>`ckl{73ndwA0DJTOyse%|n;qT$1`G7EF^3NwbKA4NmqERs;N za1ynk`NY^hCDoyz#)Rq9x8L=n{%kO-`%9!zGI?~2Mr%sEcF53_jLfVN;;}neOICWS zH7za2nv*_!;Or`0d~44Rll`r(x`2aK_THyx*hvmn z1FfO+?U{2-!Nw|8>TXY(+8R8D;sTJ}EMSs90Nzks3;$eoF5X9_ETNK0Vfpl&qdGlj zm@c}Y2aaH>_>uR6{-yRw;pr8{g`OI3Eni#4*YQ5yQ^R+1#;K+Di9xJ8X0|BeYze>P z-5pjc>xc)BQXLy`jbh-S!Qd&Sc6*JF=RGCPHg8LyqN2FK9`Lz5^|0y4F1u?!PvwG3 zLL{VRW#ktXrWPg@q~)b1rKJ|+Ck+Q{CKcw5$;nDj%g-xH&zsRM*mo!xI3sldY%M8y zR;0wvB;&EvG)4Nb;oz2~cG0e)9^&VaA4c}|);Bl;!XuU{9jvas9Zq?uH9Kv=P-{CJ z^iXTg@XQ4Z9IUpz9loRr%^{uAvla+SW#@oWy;ttcHbV2r>t>YN3tZs*UXRn));ZGX zU=^kI@q8O!o7bI4&Wz5@8_0Nt6)7-lL{&$yUIrit+|&CDFe&$KYDOdHdVf`0^y?`TT*d-of& zkjjsuRFno=8TNZ&1qU^uB_Lp@0GnMfY&gn*vk<<8!$~6jW6uhq`Uo@zC2mC{(RJv0 zGzyJIxhPNYNvfi1s-aq{+lul5*9%b*8Vd+tO!a{5%jn&7D+E*$t)2-`QdsK(B+v8l z0N^Zqw>NlOOPzCF^-gGZut~i!C<1FM0xq{J&?d~Z19%1m3=>6!r;AdD{-KBh-tVgS z{Eh@c2~oaFfFW(3Uw|;DCm?F;7u_#p2RoXH61RcRRG>;Yjj3oFnvSZ_49ZahHBu8b zQwxowR%+XZW+4Yyq!?Z`s21@kj>gj*uu2lVc)F0@43?>$?he9IIUp1)9yZbh06z!h zJ5R0CS1Z^~P*c=Mz;KcKiQnxl)lD#Zy7()h+d+b*$Y@Jvdv& zH~V-$K($lA0oZuqOY?NGZQ=^f-leiVSr)`I4uRx}Tw)aUgEL{kY{DHYUb zb@jZ*)#4Ww6Y>W?FCg~ln|-b(fSuoT(F}@c0?j^w=0i}*&`oFoS_q4@phf5wv=}X! z3LMv63n`(p*$MvxRW*WKPoTW58CJB`cC!%?!UV^U++vm2=L&5XR?47RET)MpFxK19 zQdn;px*gqt?nKMc3RDa(7Rr7l-kP9^X7wbtNzOn+a6}W}Sx>V-Kmg9>O{@#e?dhXw z^cp&x4xmX6Hf5@i;F95>L>~rKivxU9fmaZh9ELT>RV_7v79W2U3AAn%TGItsbuU^? z2ht%lnWi2?YtjACvkpCg)=%$Qt0Jfc9YhDyYyTkavqS`sO=z=&HGw8QRufZXP{bss z%h!oIP{w~46H=rL9DY3=3Qm6QG^el86{zK#yrIrVf}JUmouU>y&|{D-@_asLTPNCq zGLE6gVOzV<6KFS@TNOIkin5Yv0ap`nLT6JmO{c>sa_Au~ z>`f7<8X2yg=ruv7KRaAp;cw^-2b=IGR_KJZ3ex|~&=Axffn6nbpttFW4s?u;6bgg^ zB3_7!JN^j9LIO^rcLf2b=ye_FG`*fymkZ1z)cXNChm>9DLv$8>L`TulG`9(bO5z3*#5z7Uu4?CnQPkr!Xm^=mZh9+_>?}nP3uLTMn(LR>ShanJt_W%N0=fwF;}Q^%%jid%PYY-vEuv%T4YYVG`U(AvenD3u;Qx;PLC4YY zbPAmXaqgfu(&`yS5D7wd7x1u3Tsx>O5aB=aMnL@tFBAzF7m9)3=`)7<3g-d#3fB-l zxKkDCgGhylX>O@@yK2NTBgyY=@zwC%o5fPhBIOnw1q@4$qj3yY&=NX@j*{>>=B4_}~r zT;hKmSL1d6?xHn9ofx!lvbV0z&qF0;`>n8EqeR8xe>)~ZeOQjoV*4bFz914kRuT+1 zoPZM}SvyWZ8NE^$z6K8zQx}~{r;3>-=xTT<@-#U?)w49e>nl*>(SW-Cc0VpSnhZpjg zoD5Aq`D$K^Fiy$V@ zwP|Ip`i9`(&@y$nQCOxPH((c@O&h73Hc`(*0d=V&DWx1g31ZTa+6=(2Hc%N{R zp=BS!52M7*n`w2Z;Su~7VfHpkJMeb8=-(MF$|A?>9)pQNLkFKTn({)?$&-fR76~*DdLrM1l-Ap?mARiWrIY1BLIOa7& z-Nx4jJzl7WgnP&C>&Y^p1)}*wdk`x>8w`OyC{03OD0&r;jY5wQ-asXU;x@doh(*Tm zbzWb$AHob#q(JEH`4fcf)Z+hFY28~T{fQJQJBWm??;uh1!H{o=_>t!qB!z~?5Efj5 zDCmX`5=%GI>fY==7$ihP^l)ZGi@NA0Iut$-EqvHStKlxO7p|tKWx^d+Mp_tGNgT0- z)rhB^v@*2l05UMV=pfn^jwmvOBtZu(G_->x(}#LG(#SBOV;vpT5nMeKgCvXOgx45B zxAd%WJsA}dtt5}+gNUH>lLGokxAT*+cySlGffSQ*bQ^t??hFS2nLsA>_G&Vjl+nM? z?SeIhdyep-3B_|lZlkrgqmwCQdc@=^GK21*j{)w%R57&0c}ue+<~d1i#5|tV(Z}ho z(4yfx4RLaFZp7q9;s>Hh+@y(kh!^gt<`5sWI|Xl|1yJw(^dP;li>xH8$UXG0^fh`6ys(F` zkhMW_a=^iksQYiqQ+tCGZbSXaP$)Rvz2!X^ly}I%j{L9Wl>s4!J9MAO!9yn5M799N zkZLZ?YZ8_p9&{$oFCR52pJcAm8O|s3arL zkOP9Do+W$8b7U{sNA}a#>EGxZ^iBE}J+g%yBnN|rdI1deHoOEw9sOT1R4mrAS3@rK z7C9kU>Iiw893{udJLEWhhaRUV=t+8tzWc}Z-2a42g^ctm`Ao<{=jnSL2c5s<~KtH5s=|}V&{g{42KYfH;fxG57@(a02 zekB4iIS+^(O+TZb(=X_k@TqbdRJ`?kz+NzZy31eacGZiIOSNKi0YBGO!x#IfxS+Ix z3J&18cSqPb({0UA2LR$_8F2_7ZXzuMFnngxuw4gCBzYni+r>cc5r^E>TEIfyr20vH0 zkyMj<__;zOWc}4-J7C&N@H2$N@DqeL$XgJ#AHWX~&cTll&XdpK2MAxo)2Vc(l$pug z%p774GjB_5k_5?6NtPs6QYxvC%#iSsI!V1`k>oDP2FWH#honpLuw<)bn`FD>ImtfB z0m&iB^O6@OFH2sPye2s%`ATY(CQD~Zo29o)?~`tmZkO(m?v(D5?v_3!eMY)Rx>x$9 z^oaDR^d0F5=_%=H=^5z<(zDWY(r=>rMX95PL}f;mM0ukYN8J~-HELhfiKvTFm!d95 zU5WZxrj!|F@v>yuWZ6uaL*|s#$aq=3%q3eWTP52p+bw%b_O|Sp?6~Zt>|MD`u9h3+ zW_g_4CQp#3%16rcc`9b+%`3d}=&tBTqfbVkiRm9>jfsy*jJYOeP)u6P@R-b) z?3lcm#+c@q2V%Nn4#&J1^Me8_`Y8G-qzaiLT9Kg`qbO92Rg6=VC`uJ}#f^%3g-g+> zXi@|ea~1Ox^A$HK9#I@poKk$G_(XAD@wwtM+lTGPO4uk?&c?7Tt7L6#0y}^m$PQ+Q zut{tRo5qe}$FV%y#;##^vj^GZ>^b&3_9AM7MTsy(XbRi{;-s=ibGs_v`q zua>H1>S(oAtyde=CbdOvRgY3vsTZo(syC}U)LrVw)w|VCsh?Fpr{1SNqJCHXf%>fa zoca^>MfH#BpVYso|Ea+mM$=cL(p;lS(PV21HRCiTno^BjQ=yrnnWm}HxHavXTQqlT z?$NB)tkta3tk>++?9=Sm9MBxnyrDUwIjT9XIjMP9^Nr?5%~j3cHUHFNZH!i>)o68E zlh&fOYU8y-wHewm+OgVV?Rf1ZZJD-QTd8f(&e1N^F48X6-lkoqy+eDi_I~XH+6T28 zwcE9iYoE|QsokU9tKF|Xs6C`TtUaN9Py4?1L+vNp^V-j~UurMukgl(;zfP))(Xl$E zPOTfH8?W=|+I7oxcj%Vu?$WK)-J@Hr>(F)S9@cHuZPRVn?a=Miy{tQ~`%Ev>kI+xk z*XdpQM!iShtoP}c=vV1i>+jRA)34WW&~Md0so$gDtKYAGUjL&0W&NxA!}_!OZ}b=R z-|H{yujqf~`f*ZD#>H?fr{ve~n8@Nr}quefTH}@3x9Jh}(hS248HO7SlMS;BO$M)Fj=^teF|-=m4DE(H z49g978CDwZF|0P+XSm<+fMJ*6O~ZSJ?~O`hqH(mb#5mD7*;sC@G)^@xGp;c{XxwPr zZ0s~{Gj2ETFzz(&G9EADM*z&sNl;yPLjO7E%S<5-g zCzkVZ^0?t~RdI{r9*%o0?quBQxHEAd#(fm`aookYt5%7Xvl^{tYn;_)O|TBI4zv!o zj<8;59c9h6jxK{nDuMx&$bj>hAq>UXDhW$w%Ki! zwyC!1wtAb()@W<8{l)f-ZJ+Ic?U3yy+bg!iw%2WM+fLa&vVCd0Wc$(flkJyyCO#@& f9v>6W#w+6!;|Is51oIUlM0{t`#rM$v__Y56x5f!$ literal 0 HcmV?d00001 diff --git a/ARKit/arkitdemo.xcodeproj/project.xcworkspace/xcuserdata/mhorga.xcuserdatad/UserInterfaceState.xcuserstate b/ARKit/arkitdemo.xcodeproj/project.xcworkspace/xcuserdata/mhorga.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..ce58460f160081eccba6bd516f1b932a992636d5 GIT binary patch literal 23527 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 literal 0 HcmV?d00001 diff --git a/ARKit/arkitdemo.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ARKit/arkitdemo.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..f35774a --- /dev/null +++ b/ARKit/arkitdemo.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + arkitdemo.xcscheme + + orderHint + 0 + + + + diff --git a/ARKit/arkitdemo.xcodeproj/xcuserdata/mhorga.xcuserdatad/xcschemes/xcschememanagement.plist b/ARKit/arkitdemo.xcodeproj/xcuserdata/mhorga.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..f35774a --- /dev/null +++ b/ARKit/arkitdemo.xcodeproj/xcuserdata/mhorga.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + arkitdemo.xcscheme + + orderHint + 0 + + + + diff --git a/ARKit/arkitdemo/AppDelegate.swift b/ARKit/arkitdemo/AppDelegate.swift new file mode 100644 index 0000000..5b60f07 --- /dev/null +++ b/ARKit/arkitdemo/AppDelegate.swift @@ -0,0 +1,7 @@ + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? +} diff --git a/ARKit/arkitdemo/Base.lproj/Main.storyboard b/ARKit/arkitdemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..07ab49e --- /dev/null +++ b/ARKit/arkitdemo/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ARKit/arkitdemo/Info.plist b/ARKit/arkitdemo/Info.plist new file mode 100644 index 0000000..674bae9 --- /dev/null +++ b/ARKit/arkitdemo/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSCameraUsageDescription + This application will use the camera for Augmented Reality. + UILaunchStoryboardName + Main + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + metal + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeRight + + + diff --git a/ARKit/arkitdemo/Renderer.swift b/ARKit/arkitdemo/Renderer.swift new file mode 100644 index 0000000..1c875c8 --- /dev/null +++ b/ARKit/arkitdemo/Renderer.swift @@ -0,0 +1,298 @@ + +import MetalKit +import ARKit + +protocol RenderDestinationProvider { + var currentRenderPassDescriptor: MTLRenderPassDescriptor? { get } + var currentDrawable: CAMetalDrawable? { get } + var colorPixelFormat: MTLPixelFormat { get set } + var depthStencilPixelFormat: MTLPixelFormat { get set } + var sampleCount: Int { get set } +} + +let maxBuffersInFlight: Int = 3 +let maxAnchorInstanceCount: Int = 64 + +class Renderer { + + let session: ARSession + let device: MTLDevice + var commandQueue: MTLCommandQueue! + let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight) + var renderDestination: RenderDestinationProvider + var sharedUniformBuffer: MTLBuffer! + var anchorUniformBuffer: MTLBuffer! + var imagePlaneVertexBuffer: MTLBuffer! + var capturedImagePipelineState: MTLRenderPipelineState! + var capturedImageDepthState: MTLDepthStencilState! + var anchorPipelineState: MTLRenderPipelineState! + var anchorDepthState: MTLDepthStencilState! + var capturedImageTextureY: MTLTexture! + var capturedImageTextureCbCr: MTLTexture! + var capturedImageTextureCache: CVMetalTextureCache! + var geometryVertexDescriptor: MTLVertexDescriptor! + var mesh: MTKMesh! + var uniformBufferIndex: Int = 0 + var sharedUniformBufferOffset: Int = 0 + var anchorUniformBufferOffset: Int = 0 + var sharedUniformBufferAddress: UnsafeMutableRawPointer! + var anchorUniformBufferAddress: UnsafeMutableRawPointer! + var anchorInstanceCount: Int = 0 + var viewportSize: CGSize = CGSize() + var viewportSizeDidChange: Bool = false + + struct SharedUniforms { + var projectionMatrix: matrix_float4x4 + var viewMatrix: matrix_float4x4 + var ambientLightColor: vector_float3 + var directionalLightDirection: vector_float3 + var directionalLightColor: vector_float3 + var materialShininess: Float + } + + struct InstanceUniforms { + var modelMatrix: matrix_float4x4 + } + + let alignedSharedUniformSize = (MemoryLayout.size & ~0xFF) + 0x100 + let alignedInstanceUniformSize = ((MemoryLayout.size * maxAnchorInstanceCount) & ~0xFF) + 0x100 + let planeVertexData: [Float] = [-1, -1, 0, 1, + 1, -1, 1, 1, + -1, 1, 0, 0, + 1, 1, 1, 0] + + init(session: ARSession, metalDevice device: MTLDevice, renderDestination: RenderDestinationProvider) { + self.session = session + self.device = device + self.renderDestination = renderDestination + setupPipeline() + setupAssets() + } + + func setupPipeline() { + renderDestination.depthStencilPixelFormat = .depth32Float_stencil8 + renderDestination.colorPixelFormat = .bgra8Unorm + renderDestination.sampleCount = 1 + let sharedUniformBufferSize = alignedSharedUniformSize * maxBuffersInFlight + let anchorUniformBufferSize = alignedInstanceUniformSize * maxBuffersInFlight + sharedUniformBuffer = device.makeBuffer(length: sharedUniformBufferSize, options: .storageModeShared) + anchorUniformBuffer = device.makeBuffer(length: anchorUniformBufferSize, options: .storageModeShared) + let imagePlaneVertexDataCount = planeVertexData.count * MemoryLayout.size + imagePlaneVertexBuffer = device.makeBuffer(bytes: planeVertexData, length: imagePlaneVertexDataCount, options: []) + let defaultLibrary = device.makeDefaultLibrary()! + let capturedImageVertexFunction = defaultLibrary.makeFunction(name: "capturedImageVertexTransform")! + let capturedImageFragmentFunction = defaultLibrary.makeFunction(name: "capturedImageFragmentShader")! + let imagePlaneVertexDescriptor = MTLVertexDescriptor() + imagePlaneVertexDescriptor.attributes[0].format = .float2 + imagePlaneVertexDescriptor.attributes[0].offset = 0 + imagePlaneVertexDescriptor.attributes[0].bufferIndex = 0 + imagePlaneVertexDescriptor.attributes[1].format = .float2 + imagePlaneVertexDescriptor.attributes[1].offset = 8 + imagePlaneVertexDescriptor.attributes[1].bufferIndex = 0 + imagePlaneVertexDescriptor.layouts[0].stride = 16 + imagePlaneVertexDescriptor.layouts[0].stepRate = 1 + imagePlaneVertexDescriptor.layouts[0].stepFunction = .perVertex + let capturedImagePipelineStateDescriptor = MTLRenderPipelineDescriptor() + capturedImagePipelineStateDescriptor.label = "MyCapturedImagePipeline" + capturedImagePipelineStateDescriptor.sampleCount = renderDestination.sampleCount + capturedImagePipelineStateDescriptor.vertexFunction = capturedImageVertexFunction + capturedImagePipelineStateDescriptor.fragmentFunction = capturedImageFragmentFunction + capturedImagePipelineStateDescriptor.vertexDescriptor = imagePlaneVertexDescriptor + capturedImagePipelineStateDescriptor.colorAttachments[0].pixelFormat = renderDestination.colorPixelFormat + capturedImagePipelineStateDescriptor.depthAttachmentPixelFormat = renderDestination.depthStencilPixelFormat + capturedImagePipelineStateDescriptor.stencilAttachmentPixelFormat = renderDestination.depthStencilPixelFormat + do { try capturedImagePipelineState = device.makeRenderPipelineState(descriptor: capturedImagePipelineStateDescriptor) } + catch let error { print("Failed to created captured image pipeline state, error \(error)") } + let capturedImageDepthStateDescriptor = MTLDepthStencilDescriptor() + capturedImageDepthStateDescriptor.depthCompareFunction = .always + capturedImageDepthStateDescriptor.isDepthWriteEnabled = false + capturedImageDepthState = device.makeDepthStencilState(descriptor: capturedImageDepthStateDescriptor) + var textureCache: CVMetalTextureCache? + CVMetalTextureCacheCreate(nil, nil, device, nil, &textureCache) + capturedImageTextureCache = textureCache + let anchorGeometryVertexFunction = defaultLibrary.makeFunction(name: "anchorGeometryVertexTransform")! + let anchorGeometryFragmentFunction = defaultLibrary.makeFunction(name: "anchorGeometryFragmentLighting")! + geometryVertexDescriptor = MTLVertexDescriptor() + geometryVertexDescriptor.attributes[0].format = .float3 + geometryVertexDescriptor.attributes[0].offset = 0 + geometryVertexDescriptor.attributes[0].bufferIndex = 0 + geometryVertexDescriptor.attributes[1].format = .float2 + geometryVertexDescriptor.attributes[1].offset = 0 + geometryVertexDescriptor.attributes[1].bufferIndex = 1 + geometryVertexDescriptor.attributes[2].format = .half3 + geometryVertexDescriptor.attributes[2].offset = 8 + geometryVertexDescriptor.attributes[2].bufferIndex = 1 + geometryVertexDescriptor.layouts[0].stride = 12 + geometryVertexDescriptor.layouts[0].stepRate = 1 + geometryVertexDescriptor.layouts[0].stepFunction = .perVertex + geometryVertexDescriptor.layouts[1].stride = 16 + geometryVertexDescriptor.layouts[1].stepRate = 1 + geometryVertexDescriptor.layouts[1].stepFunction = .perVertex + let anchorPipelineStateDescriptor = MTLRenderPipelineDescriptor() + anchorPipelineStateDescriptor.label = "MyAnchorPipeline" + anchorPipelineStateDescriptor.sampleCount = renderDestination.sampleCount + anchorPipelineStateDescriptor.vertexFunction = anchorGeometryVertexFunction + anchorPipelineStateDescriptor.fragmentFunction = anchorGeometryFragmentFunction + anchorPipelineStateDescriptor.vertexDescriptor = geometryVertexDescriptor + anchorPipelineStateDescriptor.colorAttachments[0].pixelFormat = renderDestination.colorPixelFormat + anchorPipelineStateDescriptor.depthAttachmentPixelFormat = renderDestination.depthStencilPixelFormat + anchorPipelineStateDescriptor.stencilAttachmentPixelFormat = renderDestination.depthStencilPixelFormat + do { try anchorPipelineState = device.makeRenderPipelineState(descriptor: anchorPipelineStateDescriptor) } + catch let error { print("Failed to created anchor geometry pipeline state, error \(error)") } + let anchorDepthStateDescriptor = MTLDepthStencilDescriptor() + anchorDepthStateDescriptor.depthCompareFunction = .less + anchorDepthStateDescriptor.isDepthWriteEnabled = true + anchorDepthState = device.makeDepthStencilState(descriptor: anchorDepthStateDescriptor) + commandQueue = device.makeCommandQueue() + } + + func setupAssets() { + let metalAllocator = MTKMeshBufferAllocator(device: device) + let vertexDescriptor = MTKModelIOVertexDescriptorFromMetal(geometryVertexDescriptor) + (vertexDescriptor.attributes[0] as! MDLVertexAttribute).name = MDLVertexAttributePosition + (vertexDescriptor.attributes[1] as! MDLVertexAttribute).name = MDLVertexAttributeTextureCoordinate + (vertexDescriptor.attributes[2] as! MDLVertexAttribute).name = MDLVertexAttributeNormal + let mdlMesh = MDLMesh(boxWithExtent: vector3(0.075, 0.075, 0.075), segments: vector3(1, 1, 1), inwardNormals: false, geometryType: .triangles, allocator: metalAllocator) + mdlMesh.vertexDescriptor = vertexDescriptor + do { try mesh = MTKMesh(mesh: mdlMesh, device: device) } + catch let error { print("Error creating MetalKit mesh, error \(error)") } + } + + func drawRectResized(size: CGSize) { + viewportSize = size + viewportSizeDidChange = true + } + + func update() { + let _ = inFlightSemaphore.wait(timeout: DispatchTime.distantFuture) + let commandBuffer = commandQueue.makeCommandBuffer() + commandBuffer.addCompletedHandler{ [weak self] commandBuffer in + if let strongSelf = self { strongSelf.inFlightSemaphore.signal() } + return + } + updateBufferStates() + updateGameState() + guard let passDescriptor = renderDestination.currentRenderPassDescriptor, + let drawable = renderDestination.currentDrawable else { return } + let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDescriptor) + drawCapturedImage(renderEncoder: renderEncoder) + drawAnchorGeometry(renderEncoder: renderEncoder) + renderEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() + } + + func updateBufferStates() { + uniformBufferIndex = (uniformBufferIndex + 1) % maxBuffersInFlight + sharedUniformBufferOffset = alignedSharedUniformSize * uniformBufferIndex + anchorUniformBufferOffset = alignedInstanceUniformSize * uniformBufferIndex + sharedUniformBufferAddress = sharedUniformBuffer.contents().advanced(by: sharedUniformBufferOffset) + anchorUniformBufferAddress = anchorUniformBuffer.contents().advanced(by: anchorUniformBufferOffset) + } + + func updateGameState() { + guard let currentFrame = session.currentFrame else { return } + updateSharedUniforms(frame: currentFrame) + updateAnchors(frame: currentFrame) + updateCapturedImageTextures(frame: currentFrame) + if viewportSizeDidChange { + viewportSizeDidChange = false + updateImagePlane(frame: currentFrame) + } + } + + func updateSharedUniforms(frame: ARFrame) { + let uniforms = sharedUniformBufferAddress.assumingMemoryBound(to: SharedUniforms.self) + uniforms.pointee.viewMatrix = simd_inverse(frame.camera.transform) + uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(withViewportSize: viewportSize, orientation: .landscapeRight, zNear: 0.001, zFar: 1000) + var ambientIntensity: Float = 1.0 + if let lightEstimate = frame.lightEstimate { + ambientIntensity = Float(lightEstimate.ambientIntensity) / 1000.0 + } + let ambientLightColor: vector_float3 = vector3(0.5, 0.5, 0.5) + uniforms.pointee.ambientLightColor = ambientLightColor * ambientIntensity + var directionalLightDirection : vector_float3 = vector3(0.0, 0.0, -1.0) + directionalLightDirection = simd_normalize(directionalLightDirection) + uniforms.pointee.directionalLightDirection = directionalLightDirection + let directionalLightColor: vector_float3 = vector3(0.6, 0.6, 0.6) + uniforms.pointee.directionalLightColor = directionalLightColor * ambientIntensity + uniforms.pointee.materialShininess = 30 + } + + func updateAnchors(frame: ARFrame) { + anchorInstanceCount = min(frame.anchors.count, maxAnchorInstanceCount) + var anchorOffset: Int = 0 + if anchorInstanceCount == maxAnchorInstanceCount { + anchorOffset = max(frame.anchors.count - maxAnchorInstanceCount, 0) + } + for index in 0.. MTLTexture? { + var mtlTexture: MTLTexture? = nil + let width = CVPixelBufferGetWidthOfPlane(pixelBuffer, planeIndex) + let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, planeIndex) + var texture: CVMetalTexture? = nil + let status = CVMetalTextureCacheCreateTextureFromImage(nil, capturedImageTextureCache, pixelBuffer, nil, pixelFormat, width, height, planeIndex, &texture) + if status == kCVReturnSuccess { mtlTexture = CVMetalTextureGetTexture(texture!) } + return mtlTexture + } + + func updateImagePlane(frame: ARFrame) { + let displayToCameraTransform = frame.displayTransform(withViewportSize: viewportSize, orientation: .landscapeRight).inverted() + let vertexData = imagePlaneVertexBuffer.contents().assumingMemoryBound(to: Float.self) + for index in 0...3 { + let textureCoordIndex = 4 * index + 2 + let textureCoord = CGPoint(x: CGFloat(planeVertexData[textureCoordIndex]), y: CGFloat(planeVertexData[textureCoordIndex + 1])) + let transformedCoord = textureCoord.applying(displayToCameraTransform) + vertexData[textureCoordIndex] = Float(transformedCoord.x) + vertexData[textureCoordIndex + 1] = Float(transformedCoord.y) + } + } + + func drawCapturedImage(renderEncoder: MTLRenderCommandEncoder) { + guard capturedImageTextureY != nil && capturedImageTextureCbCr != nil else { return } + renderEncoder.pushDebugGroup("DrawCapturedImage") + renderEncoder.setCullMode(.none) + renderEncoder.setRenderPipelineState(capturedImagePipelineState) + renderEncoder.setDepthStencilState(capturedImageDepthState) + renderEncoder.setVertexBuffer(imagePlaneVertexBuffer, offset: 0, index: 0) + renderEncoder.setFragmentTexture(capturedImageTextureY, index: 1) + renderEncoder.setFragmentTexture(capturedImageTextureCbCr, index: 2) + renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4) + renderEncoder.popDebugGroup() + } + + func drawAnchorGeometry(renderEncoder: MTLRenderCommandEncoder) { + guard anchorInstanceCount > 0 else { return } + renderEncoder.pushDebugGroup("DrawAnchors") + renderEncoder.setCullMode(.back) + renderEncoder.setRenderPipelineState(anchorPipelineState) + renderEncoder.setDepthStencilState(anchorDepthState) + renderEncoder.setVertexBuffer(anchorUniformBuffer, offset: anchorUniformBufferOffset, index: 2) + renderEncoder.setVertexBuffer(sharedUniformBuffer, offset: sharedUniformBufferOffset, index: 3) + renderEncoder.setFragmentBuffer(sharedUniformBuffer, offset: sharedUniformBufferOffset, index: 3) + for bufferIndex in 0.. +using namespace metal; + +typedef struct { + float2 position [[attribute(0)]]; + float2 texCoord [[attribute(1)]]; +} ImageVertex; + +typedef struct { + float4 position [[position]]; + float2 texCoord; +} ImageColorInOut; + +typedef struct { + float4x4 projectionMatrix; + float4x4 viewMatrix; + float3 ambientLightColor; + float3 directionalLightDirection; + float3 directionalLightColor; + float materialShininess; +} SharedUniforms; + +typedef struct { + float4x4 modelMatrix; +} InstanceUniforms; + +vertex ImageColorInOut capturedImageVertexTransform(ImageVertex in [[stage_in]]) { + ImageColorInOut out; + out.position = float4(in.position, 0.0, 1.0); + out.texCoord = in.texCoord; + return out; +} + +fragment float4 capturedImageFragmentShader(ImageColorInOut in [[stage_in]], + texture2d textureY [[ texture(1) ]], + texture2d textureCbCr [[ texture(2) ]]) { + constexpr sampler colorSampler(mip_filter::linear, mag_filter::linear, min_filter::linear); + const float4x4 ycbcrToRGBTransform = float4x4(float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f), + float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f), + float4(+1.4020f, -0.7141f, +0.0000f, +0.0000f), + float4(-0.7010f, +0.5291f, -0.8860f, +1.0000f)); + float4 ycbcr = float4(textureY.sample(colorSampler, in.texCoord).r, textureCbCr.sample(colorSampler, in.texCoord).rg, 1.0); + return ycbcrToRGBTransform * ycbcr; +} + +typedef struct { + float3 position [[attribute(0)]]; + float2 texCoord [[attribute(1)]]; + half3 normal [[attribute(2)]]; +} Vertex; + +typedef struct { + float4 position [[position]]; + float4 color; + half3 eyePosition; + half3 normal; +} ColorInOut; + +vertex ColorInOut anchorGeometryVertexTransform(Vertex in [[stage_in]], + constant SharedUniforms &sharedUniforms [[ buffer(3) ]], + constant InstanceUniforms *instanceUniforms [[ buffer(2) ]], + ushort vid [[vertex_id]], + ushort iid [[instance_id]]) { + ColorInOut out; + float4 position = float4(in.position, 1.0); + float4x4 modelMatrix = instanceUniforms[iid].modelMatrix; + float4x4 modelViewMatrix = sharedUniforms.viewMatrix * modelMatrix; + out.position = sharedUniforms.projectionMatrix * modelViewMatrix * position; + ushort colorID = vid / 4 % 6; + out.color = colorID == 0 ? float4(0.0, 1.0, 0.0, 1.0) // Right face + : colorID == 1 ? float4(1.0, 0.0, 0.0, 1.0) // Left face + : colorID == 2 ? float4(0.0, 0.0, 1.0, 1.0) // Top face + : colorID == 3 ? float4(1.0, 0.5, 0.0, 1.0) // Bottom face + : colorID == 4 ? float4(1.0, 1.0, 0.0, 1.0) // Back face + : float4(1.0, 1.0, 1.0, 1.0); // Front face + out.eyePosition = half3((modelViewMatrix * position).xyz); + float4 normal = modelMatrix * float4(in.normal.x, in.normal.y, in.normal.z, 0.0f); + out.normal = normalize(half3(normal.xyz)); + return out; +} + +fragment float4 anchorGeometryFragmentLighting(ColorInOut in [[stage_in]], + constant SharedUniforms &uniforms [[ buffer(3) ]]) { + float3 normal = float3(in.normal); + float3 directionalContribution = float3(0); + { + float nDotL = saturate(dot(normal, -uniforms.directionalLightDirection)); + float3 diffuseTerm = uniforms.directionalLightColor * nDotL; + float3 halfwayVector = normalize(-uniforms.directionalLightDirection - float3(in.eyePosition)); + float reflectionAngle = saturate(dot(normal, halfwayVector)); + float specularIntensity = saturate(powr(reflectionAngle, uniforms.materialShininess)); + float3 specularTerm = uniforms.directionalLightColor * specularIntensity; + directionalContribution = diffuseTerm + specularTerm; + } + float3 ambientContribution = uniforms.ambientLightColor; + float3 lightContributions = ambientContribution + directionalContribution; + float3 color = in.color.rgb * lightContributions; + return float4(color, in.color.w); +} diff --git a/ARKit/arkitdemo/ViewController.swift b/ARKit/arkitdemo/ViewController.swift new file mode 100644 index 0000000..5a5ae5e --- /dev/null +++ b/ARKit/arkitdemo/ViewController.swift @@ -0,0 +1,61 @@ + +import MetalKit +import ARKit + +extension MTKView : RenderDestinationProvider {} + +class ViewController: UIViewController, MTKViewDelegate, ARSessionDelegate { + + var session: ARSession! + var renderer: Renderer! + + override func viewDidLoad() { + super.viewDidLoad() + session = ARSession() + session.delegate = self + if let view = self.view as? MTKView { + view.device = MTLCreateSystemDefaultDevice() + view.delegate = self + renderer = Renderer(session: session, metalDevice: view.device!, renderDestination: view) + renderer.drawRectResized(size: view.bounds.size) + } + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(gestureRecognize:))) + view.addGestureRecognizer(tapGesture) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + let configuration = ARWorldTrackingSessionConfiguration() + session.run(configuration) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + session.pause() + } + + @objc + func handleTap(gestureRecognize: UITapGestureRecognizer) { + if let currentFrame = session.currentFrame { + var translation = matrix_identity_float4x4 + translation.columns.3.z = -0.2 + let transform = simd_mul(currentFrame.camera.transform, translation) + let anchor = ARAnchor(transform: transform) + session.add(anchor: anchor) + } + } + + func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { + renderer.drawRectResized(size: size) + } + + func draw(in view: MTKView) { + renderer.update() + } + + func session(_ session: ARSession, didFailWithError error: Error) {} + + func sessionWasInterrupted(_ session: ARSession) {} + + func sessionInterruptionEnded(_ session: ARSession) {} +} diff --git a/README.md b/README.md index b3a760a..0d1e666 100644 --- a/README.md +++ b/README.md @@ -27,3 +27,4 @@ Repository to accompany the following blog posts: - [Working with memory in Metal](http://metalkit.org/2017/04/30/working-with-memory-in-metal.html) - [Working with memory in Metal part 2](http://metalkit.org/2017/05/26/working-with-memory-in-metal-part-2.html) - [Introducing Metal 2](http://metalkit.org/2017/06/30/introducing-metal-2.html) +- [Using ARKit with Metal](http://metalkit.org/2017/07/29/using-arkit-with-metal.html)