├── .gitignore
├── ArtzyCamera.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcshareddata
│ └── xcschemes
│ │ └── ArtzyCamera.xcscheme
└── xcuserdata
│ └── oscardelaheragomez.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── ArtzyCamera
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AR Resources.arresourcegroup
│ │ ├── Contents.json
│ │ ├── artzy loader by delasign.arreferenceimage
│ │ │ ├── 1024.png
│ │ │ └── Contents.json
│ │ ├── hand by delasign.arreferenceimage
│ │ │ ├── Contents.json
│ │ │ └── Hand-02.png
│ │ ├── local by adamfu x delasign.arreferenceimage
│ │ │ ├── Contents.json
│ │ │ └── adamLocal-01.png
│ │ └── mondriaan by delasign.arreferenceimage
│ │ │ ├── Contents.json
│ │ │ └── Painting@3x.png
│ ├── AppIcon.appiconset
│ │ ├── 1024.png
│ │ ├── 20.png
│ │ ├── 20@2x-1.png
│ │ ├── 20@2x.png
│ │ ├── 20@3x.png
│ │ ├── 29.png
│ │ ├── 29@2x-1.png
│ │ ├── 29@2x.png
│ │ ├── 29@3x.png
│ │ ├── 40.png
│ │ ├── 40@2x-1.png
│ │ ├── 40@2x.png
│ │ ├── 40@3x.png
│ │ ├── 60@2x.png
│ │ ├── 60@3x.png
│ │ ├── 76.png
│ │ ├── 76@2x.png
│ │ ├── 83.5.png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── LaunchImage.launchimage
│ │ ├── Contents.json
│ │ ├── Ipad Portrait.png
│ │ ├── Ipad Portrait@2x.png
│ │ ├── Retina HD 5.5.png
│ │ ├── Retine HD 4.7".png
│ │ ├── XR.png
│ │ ├── XS Max.png
│ │ └── xs.png
│ └── saveIcon.imageset
│ │ ├── ArtzyLogo-01@2x.png
│ │ ├── ArtzyLogo-01@3x.png
│ │ ├── ArtzyLogo-1.png
│ │ └── Contents.json
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── HUD
│ ├── BaseView
│ │ └── BaseView.swift
│ ├── Buttons
│ │ ├── Camera
│ │ │ └── ArtzyCameraButton.swift
│ │ ├── Cancel
│ │ │ └── CancelButton.swift
│ │ ├── Reset
│ │ │ └── ResetButton.swift
│ │ └── Save
│ │ │ └── SaveButton.swift
│ ├── CameraHUDViewControllerViewController.swift
│ ├── Functionality
│ │ ├── HUDAudioFunc.swift
│ │ ├── HUDPhotoFunc.swift
│ │ ├── HUDRecordingFunc.swift
│ │ └── HUDVideoFunc.swift
│ ├── NotificationView
│ │ ├── NotificationBlimp.swift
│ │ └── NotificationView.swift
│ └── Preview
│ │ └── PreviewView.swift
├── Info.plist
├── PieceOfArtzy
│ ├── Functionality
│ │ └── ShaderFunctionality.swift
│ ├── PieceOfArtzy.swift
│ ├── Shaders
│ │ ├── Fade
│ │ │ ├── FadeIn.metal
│ │ │ └── FadeInTexture.metal
│ │ ├── Standard
│ │ │ ├── Color.metal
│ │ │ └── Texture.metal
│ │ └── Stroke
│ │ │ ├── BackwardStroke.metal
│ │ │ ├── BackwardsTimedStroke.metal
│ │ │ ├── BackwardsTimedStrokeTexture.metal
│ │ │ ├── Stroke.metal
│ │ │ ├── TimedStroke.metal
│ │ │ └── TimedStrokeTexture.metal
│ ├── SpecialEffects
│ │ ├── Glow
│ │ │ ├── Glow.metal
│ │ │ └── Glow.plist
│ │ └── GlowInTwoColors
│ │ │ ├── GlowBlue.metal
│ │ │ ├── GlowInTwoColors.plist
│ │ │ └── GlowRed.metal
│ └── Variables
│ │ └── PieceOfArtzyVariables.swift
├── Variables
│ └── AppVariables.swift
├── ViewController.swift
└── art.scnassets
│ ├── hand.dae
│ └── localxAdamfu.scn
├── ArtzyCameraTests
├── ArtzyCameraTests.swift
└── Info.plist
├── ArtzyCameraUITests
├── ArtzyCameraUITests.swift
└── Info.plist
├── GettingStarted
├── Hand-02.png
├── a4Logo-01.png
└── adamLocal-01.png
├── HowItWasMade
├── Hand
│ ├── Files
│ │ ├── Hand8.ai
│ │ └── hand.mb
│ └── Image
│ │ └── Hand-02.png
├── Loader
│ ├── Files
│ │ ├── Loading.mb
│ │ ├── loading8.ai
│ │ └── logo.scn
│ └── Image
│ │ └── 1024.png
└── Local
│ ├── Files
│ ├── adamLocal8.ai
│ ├── adamLocal8Halo.ai
│ └── adamLocalFinal.mb
│ └── Image
│ └── adamLocal-01.png
├── README.md
└── license.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | # Swift Package Manager
31 | #
32 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
33 | # Packages/
34 | .build/
35 |
36 | # CocoaPods
37 | #
38 | # We recommend against adding the Pods directory to your .gitignore. However
39 | # you should judge for yourself, the pros and cons are mentioned at:
40 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
41 | #
42 | # Pods/
43 |
44 | .DS_Store
45 | ArtzyCamera.xcworkspace/xcuserdata/oscardelaheragomez.xcuserdatad/UserInterfaceState.xcuserstate
46 |
47 |
--------------------------------------------------------------------------------
/ArtzyCamera.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ArtzyCamera.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ArtzyCamera.xcodeproj/xcshareddata/xcschemes/ArtzyCamera.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/ArtzyCamera.xcodeproj/xcuserdata/oscardelaheragomez.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ArtzyCamera.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | BA82E20121B5C85D002CEFE4
16 |
17 | primary
18 |
19 |
20 | BA82E21721B5C860002CEFE4
21 |
22 | primary
23 |
24 |
25 | BA82E22221B5C860002CEFE4
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ArtzyCamera/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | },
6 | "resources" : [
7 | {
8 | "filename" : "artzy loader by delasign.arreferenceimage"
9 | },
10 | {
11 | "filename" : "hand by delasign.arreferenceimage"
12 | },
13 | {
14 | "filename" : "local by adamfu x delasign.arreferenceimage"
15 | },
16 | {
17 | "filename" : "mondriaan by delasign.arreferenceimage"
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/artzy loader by delasign.arreferenceimage/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/artzy loader by delasign.arreferenceimage/1024.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/artzy loader by delasign.arreferenceimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1024.png"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | },
12 | "properties" : {
13 | "width" : 0.20000000000000001
14 | }
15 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/hand by delasign.arreferenceimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Hand-02.png"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | },
12 | "properties" : {
13 | "width" : 0.17000000000000001
14 | }
15 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/hand by delasign.arreferenceimage/Hand-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/hand by delasign.arreferenceimage/Hand-02.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/local by adamfu x delasign.arreferenceimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "adamLocal-01.png"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | },
12 | "properties" : {
13 | "width" : 0.20999999999999999
14 | }
15 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/local by adamfu x delasign.arreferenceimage/adamLocal-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/local by adamfu x delasign.arreferenceimage/adamLocal-01.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/mondriaan by delasign.arreferenceimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Painting@3x.png"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | },
12 | "properties" : {
13 | "width" : 0.20000000000000001
14 | }
15 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/mondriaan by delasign.arreferenceimage/Painting@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AR Resources.arresourcegroup/mondriaan by delasign.arreferenceimage/Painting@3x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/1024.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20@2x-1.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/20@3x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29@2x-1.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/29@3x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40@2x-1.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/40@3x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/60@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/60@3x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/76.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/76@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/83.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/83.5.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "29@2x.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "29@3x.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "40x40",
29 | "idiom" : "iphone",
30 | "filename" : "40@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "40@3x.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "size" : "60x60",
41 | "idiom" : "iphone",
42 | "filename" : "60@2x.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "60@3x.png",
49 | "scale" : "3x"
50 | },
51 | {
52 | "size" : "20x20",
53 | "idiom" : "ipad",
54 | "filename" : "20.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "20@2x-1.png",
61 | "scale" : "2x"
62 | },
63 | {
64 | "size" : "29x29",
65 | "idiom" : "ipad",
66 | "filename" : "29.png",
67 | "scale" : "1x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "29@2x-1.png",
73 | "scale" : "2x"
74 | },
75 | {
76 | "size" : "40x40",
77 | "idiom" : "ipad",
78 | "filename" : "40.png",
79 | "scale" : "1x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "40@2x-1.png",
85 | "scale" : "2x"
86 | },
87 | {
88 | "size" : "76x76",
89 | "idiom" : "ipad",
90 | "filename" : "76.png",
91 | "scale" : "1x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "76@2x.png",
97 | "scale" : "2x"
98 | },
99 | {
100 | "size" : "83.5x83.5",
101 | "idiom" : "ipad",
102 | "filename" : "83.5.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "1024x1024",
107 | "idiom" : "ios-marketing",
108 | "filename" : "1024.png",
109 | "scale" : "1x"
110 | }
111 | ],
112 | "info" : {
113 | "version" : 1,
114 | "author" : "xcode"
115 | }
116 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "2688h",
7 | "filename" : "XS Max.png",
8 | "minimum-system-version" : "12.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "1792h",
16 | "filename" : "XR.png",
17 | "minimum-system-version" : "12.0",
18 | "orientation" : "portrait",
19 | "scale" : "2x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "2436h",
25 | "filename" : "xs.png",
26 | "minimum-system-version" : "11.0",
27 | "orientation" : "portrait",
28 | "scale" : "3x"
29 | },
30 | {
31 | "extent" : "full-screen",
32 | "idiom" : "iphone",
33 | "subtype" : "736h",
34 | "filename" : "Retina HD 5.5.png",
35 | "minimum-system-version" : "8.0",
36 | "orientation" : "portrait",
37 | "scale" : "3x"
38 | },
39 | {
40 | "extent" : "full-screen",
41 | "idiom" : "iphone",
42 | "subtype" : "667h",
43 | "filename" : "Retine HD 4.7\".png",
44 | "minimum-system-version" : "8.0",
45 | "orientation" : "portrait",
46 | "scale" : "2x"
47 | },
48 | {
49 | "orientation" : "portrait",
50 | "idiom" : "ipad",
51 | "filename" : "Ipad Portrait.png",
52 | "extent" : "full-screen",
53 | "minimum-system-version" : "7.0",
54 | "scale" : "1x"
55 | },
56 | {
57 | "orientation" : "portrait",
58 | "idiom" : "ipad",
59 | "filename" : "Ipad Portrait@2x.png",
60 | "extent" : "full-screen",
61 | "minimum-system-version" : "7.0",
62 | "scale" : "2x"
63 | }
64 | ],
65 | "info" : {
66 | "version" : 1,
67 | "author" : "xcode"
68 | }
69 | }
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Ipad Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Ipad Portrait.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Ipad Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Ipad Portrait@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Retina HD 5.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Retina HD 5.5.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Retine HD 4.7".png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/Retine HD 4.7".png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/XR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/XR.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/XS Max.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/XS Max.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/xs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/LaunchImage.launchimage/xs.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/saveIcon.imageset/ArtzyLogo-01@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/saveIcon.imageset/ArtzyLogo-01@2x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/saveIcon.imageset/ArtzyLogo-01@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/saveIcon.imageset/ArtzyLogo-01@3x.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/saveIcon.imageset/ArtzyLogo-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/Assets.xcassets/saveIcon.imageset/ArtzyLogo-1.png
--------------------------------------------------------------------------------
/ArtzyCamera/Assets.xcassets/saveIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "ArtzyLogo-1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "ArtzyLogo-01@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "ArtzyLogo-01@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/ArtzyCamera/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 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/ArtzyCamera/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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/BaseView/BaseView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseView.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/4/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import AVFoundation
12 | import ARKit
13 |
14 | class BaseView: UIView {
15 |
16 | public var cameraHUDDelegate:CameraHUDDelegate?
17 | public var viewControllerDelegate:ViewControllerDelegate?;
18 | public var sceneView:ARSCNView = ARSCNView();
19 |
20 | var cameraButton: ArtzyCameraButton = ArtzyCameraButton();
21 | var resetButton:ResetButton = ResetButton();
22 |
23 | override init(frame: CGRect) {
24 | super.init(frame: frame);
25 | self.alpha = 1;
26 |
27 |
28 |
29 |
30 | }
31 |
32 | public func start() {
33 | self.cameraButton = ArtzyCameraButton();
34 | self.cameraButton.sceneView = self.sceneView;
35 | self.cameraButton.cameraHUDDelegate = self.cameraHUDDelegate;
36 |
37 | self.addSubview(self.cameraButton);
38 |
39 | self.resetButton = ResetButton();
40 | self.resetButton.viewControllerDelegate = self.viewControllerDelegate;
41 | self.resetButton.cameraHUDDelegate = self.cameraHUDDelegate;
42 | self.addSubview(self.resetButton);
43 | }
44 |
45 | required init?(coder aDecoder: NSCoder) {
46 | super.init(coder: aDecoder);
47 | }
48 |
49 | func generateAttributedTitle(string:String, size:CGFloat) -> NSMutableAttributedString{
50 | return NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.foregroundColor: UIColor.black, NSAttributedString.Key.font: UIFont(name: "Helvetica", size: size)]);
51 | }
52 |
53 | public func showBaseView(withURL:URL) {
54 | self.alpha = 1
55 | self.isUserInteractionEnabled = true;
56 | }
57 |
58 | private func hideBaseView() {
59 | self.alpha = 0
60 | self.isUserInteractionEnabled = false;
61 | }
62 |
63 | // MARK : BUTTON FUNCTIONALITY
64 |
65 | // @objc private func resetButtonPressed() {
66 | // self.cameraHUDDelegate?.exportVideo();
67 | // self.removeVideoPreview();
68 | // self.hideBaseView();
69 | // }
70 | //
71 | // @objc private func cancelButtonPressed() {
72 | // self.removeVideoPreview();
73 | // FileManager.default.clearTmpDirectory();
74 | // self.hideBaseView();
75 | // }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Buttons/Camera/ArtzyCameraButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArtzyCameraButton.swift
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/2/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ARKit
11 | import Photos
12 | import ReplayKit
13 |
14 | class ArtzyCameraButton: UIButton {
15 |
16 | public var sceneView:ARSCNView = ARSCNView();
17 | // public var xArtAlertViewDelegate:xAlertViewDelegate?;
18 | public var cameraHUDDelegate:CameraHUDDelegate?;
19 |
20 | private let whiteCircle:UIView = UIView();
21 | private var whiteCircleSize:CGFloat {
22 | return kArtzyCameraButtonDimension*3/4;
23 | }
24 |
25 | private let videoCameraProgressArc:CAShapeLayer = CAShapeLayer();
26 | private var videoCameraProgressArcMargin:CGFloat {
27 | return kArtzyCameraButtonDimension/20;
28 | }
29 |
30 | private let circleGrowthTimeInterval:TimeInterval = 0.3;
31 | private var touchEnded:Bool = false;
32 | private var videoStarted:Bool = false;
33 | private var videoSaved:Bool = false;
34 |
35 | init() {
36 | // Initialize the view to fit the responsive design presented in the deck and sketch file
37 | // Instatiate Camera Circle
38 |
39 | super.init(frame: CGRect(x: (screenWidth - kArtzyCameraButtonDimension)/2, y: (screenHeight*0.9-kArtzyCameraButtonDimension), width: kArtzyCameraButtonDimension, height: kArtzyCameraButtonDimension));
40 |
41 | self.backgroundColor = UIColor.white.withAlphaComponent(0.6);
42 | self.layer.cornerRadius = kArtzyCameraButtonDimension/2;
43 |
44 | // Instatiate Camera Circle
45 |
46 | self.whiteCircle.backgroundColor = UIColor.white;
47 | self.whiteCircle.layer.cornerRadius = whiteCircleSize/2;
48 | self.whiteCircle.frame = CGRect(x: (self.frame.width-whiteCircleSize)/2, y: (self.frame.width-whiteCircleSize)/2, width: whiteCircleSize, height: whiteCircleSize);
49 | self.addSubview(self.whiteCircle);
50 |
51 |
52 | // Create the video camera progress arc
53 |
54 | self.videoCameraProgressArc.opacity = 0;
55 | self.videoCameraProgressArc.path = UIBezierPath(ovalIn: CGRect(x: self.videoCameraProgressArcMargin, y: self.videoCameraProgressArcMargin, width: self.frame.width - self.videoCameraProgressArcMargin*2, height: self.frame.width - self.videoCameraProgressArcMargin*2)).cgPath;
56 | self.videoCameraProgressArc.lineWidth = 5.0;
57 | self.videoCameraProgressArc.strokeStart = 0;
58 | self.videoCameraProgressArc.strokeEnd = 0;
59 | self.videoCameraProgressArc.strokeColor = UIColor.black.cgColor;
60 | self.videoCameraProgressArc.fillColor = UIColor.clear.cgColor;
61 |
62 | // Rotate 90 degrees anti clockwise
63 | self.videoCameraProgressArc.transform = CATransform3DMakeRotation(CGFloat(-Double.pi/2), 0,0,1);
64 | self.videoCameraProgressArc.position = CGPoint(x: 0, y: self.frame.height);
65 |
66 |
67 | self.layer.addSublayer(self.videoCameraProgressArc);
68 |
69 |
70 |
71 | }
72 |
73 | override init(frame: CGRect) {
74 | super.init(frame: frame);
75 |
76 | }
77 |
78 | required init?(coder aDecoder: NSCoder) {
79 | super.init(coder: aDecoder);
80 | }
81 |
82 | // BUTTON FUNCTIONALITY
83 |
84 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
85 |
86 | self.touchEnded = false;
87 | self.videoSaved = false;
88 |
89 | UIView.animate(withDuration: circleGrowthTimeInterval, delay: 0, options: .curveEaseInOut, animations: {
90 |
91 | self.frame = CGRect(x: (screenWidth - kArtzyCameraButtonDimension*1.5)/2, y: (screenHeight*0.9-kArtzyCameraButtonDimension*1.25), width: kArtzyCameraButtonDimension*1.5, height: kArtzyCameraButtonDimension*1.5);
92 | self.layer.cornerRadius = kArtzyCameraButtonDimension*1.5/2;
93 |
94 | self.whiteCircle.frame = CGRect(x: (self.frame.width-self.whiteCircleSize)/2, y: (self.frame.width-self.whiteCircleSize)/2, width: self.whiteCircleSize, height: self.whiteCircleSize);
95 |
96 | self.videoCameraProgressArc.path = UIBezierPath(ovalIn: CGRect(x: self.videoCameraProgressArcMargin, y: self.videoCameraProgressArcMargin, width: self.frame.width - self.videoCameraProgressArcMargin*2, height: self.frame.width - self.videoCameraProgressArcMargin*2)).cgPath;
97 |
98 | self.videoCameraProgressArc.transform = CATransform3DMakeRotation(CGFloat(-Double.pi/2), 0,0,1);
99 | self.videoCameraProgressArc.position = CGPoint(x: 0, y: self.frame.height);
100 |
101 | }) { (finished) in
102 | print("FINISHED INWARD ANIMATION");
103 | // Begin Video Capture
104 |
105 | if (self.touchEnded == false){
106 |
107 | self.videoStarted = true;
108 |
109 | // Start the animation
110 | self.animateVideoRing();
111 |
112 | // Start recording the video
113 | self.cameraHUDDelegate?.startRecording();
114 | }
115 | }
116 | }
117 |
118 | override func touchesMoved(_ touches: Set, with event: UIEvent?) {
119 |
120 | }
121 |
122 | override func touchesEnded(_ touches: Set, with event: UIEvent?) {
123 |
124 | self.touchEnded = true;
125 |
126 |
127 | print("STATE ", RPScreenRecorder.shared().isRecording )
128 | print("VIDEO STARTED ", self.videoStarted )
129 |
130 | if( self.videoStarted == false ){ //self.recorder?.status != .recording
131 | // Check if you actually started recording?
132 | if self.videoSaved == false {
133 | print("IMAGE");
134 | self.cameraHUDDelegate?.previewPhoto(image:self.sceneView.snapshot());
135 |
136 | }
137 | else {
138 | print("Video Already saved");
139 | }
140 | }
141 | else {
142 | self.videoStarted = false;
143 |
144 | // Screen Recorder isn't recording, theresfore stop recording.
145 | print("VIDEO");
146 | self.videoCameraProgressArc.removeAllAnimations();
147 | self.videoCameraProgressArc.opacity = 0;
148 | }
149 |
150 | UIView.animate(withDuration: circleGrowthTimeInterval, animations: {
151 |
152 | self.frame = CGRect(x: (screenWidth - kArtzyCameraButtonDimension)/2, y: (screenHeight*0.9-kArtzyCameraButtonDimension), width: kArtzyCameraButtonDimension, height: kArtzyCameraButtonDimension);
153 | self.layer.cornerRadius = kArtzyCameraButtonDimension/2;
154 |
155 | self.whiteCircle.frame = CGRect(x: (self.frame.width-self.whiteCircleSize)/2, y: (self.frame.width-self.whiteCircleSize)/2, width: self.whiteCircleSize, height: self.whiteCircleSize);
156 |
157 | });
158 |
159 | }
160 |
161 | // MARK : ANIMATION FUNCTIONALITY
162 |
163 | func animateVideoRing(){
164 | // Set the Initial Stroke State
165 | self.videoCameraProgressArc.strokeStart = 0
166 | self.videoCameraProgressArc.strokeEnd = 0
167 | self.videoCameraProgressArc.opacity = 1;
168 |
169 | CATransaction.begin();
170 | CATransaction.setAnimationDuration(10);
171 | CATransaction.setDisableActions(true);
172 | CATransaction.setCompletionBlock {
173 | self.videoRingAnimationDidFinish();
174 | }
175 |
176 | // Set animation end state
177 | let start = CABasicAnimation(keyPath: "strokeStart")
178 | start.toValue = 0
179 | let end = CABasicAnimation(keyPath: "strokeEnd")
180 | end.toValue = 1
181 |
182 | // Play Animation Repetitively
183 | let group = CAAnimationGroup()
184 | group.animations = [start, end];
185 | group.duration = 10
186 | group.autoreverses = false;
187 | group.repeatCount = 0 // repeat 0 times
188 | group.isRemovedOnCompletion = true;
189 |
190 | self.videoCameraProgressArc.add(group, forKey: nil)
191 |
192 | CATransaction.commit();
193 |
194 | }
195 |
196 | func videoRingAnimationDidFinish(){
197 | print("STOP VIDEO, ANIMATION COMPLETE");
198 |
199 | // Stop the button animation and hide the arc
200 | self.videoCameraProgressArc.removeAllAnimations();
201 | self.videoCameraProgressArc.opacity = 0;
202 | self.videoSaved = true;
203 | self.cameraHUDDelegate?.stopRecording();
204 | }
205 |
206 | }
207 |
208 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Buttons/Cancel/CancelButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CancelButton.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/5/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CancelButton: UIButton {
12 |
13 | public var viewControllerDelegate:ViewControllerDelegate?;
14 | public var cameraHUDDelegate:CameraHUDDelegate?;
15 |
16 | private var label:UILabel = UILabel();
17 |
18 | init() {
19 | // Initialize the view to fit the responsive design presented in the deck and sketch file
20 | // Instatiate Camera Circle
21 |
22 | super.init(frame: CGRect(x: kArtzyHUDButtonGap/2, y:kArtzyResetButtonMinY, width: kArtzyResetButtonDimension, height: kArtzyResetButtonDimension));
23 | self.layer.cornerRadius = 6;
24 |
25 | self.label.attributedText = self.generateAttributedTitle(string: "cancel", size: 18);
26 | self.label.sizeToFit();
27 | self.label.frame = CGRect(x: 0, y: kArtzMinYLabelLine-self.frame.minY, width: self.label.frame.width, height: self.label.frame.height);
28 |
29 | self.addSubview(self.label);
30 | }
31 |
32 | override init(frame: CGRect) {
33 | super.init(frame: frame);
34 |
35 | }
36 |
37 | required init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder);
39 | }
40 |
41 | func generateAttributedTitle(string:String, size:CGFloat) -> NSMutableAttributedString{
42 | return NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont(name: "Helvetica", size: size)]);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Buttons/Reset/ResetButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ResetButton.swift
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 9/15/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ResetButton: UIButton {
12 |
13 | public var viewControllerDelegate:ViewControllerDelegate?;
14 | public var cameraHUDDelegate:CameraHUDDelegate?;
15 |
16 | private var label:UILabel = UILabel();
17 |
18 | init() {
19 | // Initialize the view to fit the responsive design presented in the deck and sketch file
20 | // Instatiate Camera Circle
21 |
22 | super.init(frame: CGRect(x: screenWidth - kArtzyResetButtonDimension - kArtzyHUDButtonGap/2, y:kArtzyResetButtonMinY, width: kArtzyResetButtonDimension, height: kArtzyResetButtonDimension));
23 | // self.setAttributedTitle(self.generateAttributedTitle(string: "reset", size: 18), for: .normal);
24 | self.layer.cornerRadius = 6;
25 |
26 | self.label.attributedText = self.generateAttributedTitle(string: "reset", size: 18);
27 | self.label.sizeToFit();
28 | self.label.frame = CGRect(x: 0, y: kArtzMinYLabelLine-self.frame.minY, width: self.frame.width, height: self.label.frame.height);
29 | self.addSubview(self.label);
30 | }
31 |
32 | override init(frame: CGRect) {
33 | super.init(frame: frame);
34 |
35 | }
36 |
37 | required init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder);
39 | }
40 |
41 | func generateAttributedTitle(string:String, size:CGFloat) -> NSMutableAttributedString{
42 | return NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont(name: "Helvetica", size: size)]);
43 | }
44 |
45 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
46 | DispatchQueue.global().async { [weak self] in
47 | self?.cameraHUDDelegate?.resetCameraHUD();
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Buttons/Save/SaveButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SaveButton.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/5/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SaveButton: UIButton {
12 |
13 | public var viewControllerDelegate:ViewControllerDelegate?;
14 | public var cameraHUDDelegate:CameraHUDDelegate?;
15 |
16 | private var label:UILabel = UILabel();
17 | private var saveIcon:UIImageView = UIImageView(); //UIImage(named: "saveIcon");
18 |
19 | init() {
20 | // Initialize the view to fit the responsive design presented in the deck and sketch file
21 | // Instatiate Camera Circle
22 |
23 | var kArtzySaveButtonDimension:CGFloat = CGFloat();
24 | kArtzySaveButtonDimension = screenHeight/6
25 |
26 | super.init(frame: CGRect(x: (screenWidth-kArtzySaveButtonDimension)/2, y:screenHeight*0.7325, width: kArtzySaveButtonDimension, height: kArtzySaveButtonDimension));
27 | self.layer.cornerRadius = 6;
28 |
29 | self.label.attributedText = self.generateAttributedTitle(string: "save", size: 18);
30 | self.label.sizeToFit();
31 | self.label.textAlignment = .center;
32 | self.label.frame = CGRect(x: 0, y: self.frame.height*0.75, width: self.frame.width, height: self.label.frame.height);
33 | self.addSubview(self.label);
34 |
35 | self.saveIcon.frame = CGRect(x: self.frame.height*0.25, y: self.frame.height*0.125, width: self.frame.height*0.5, height: self.frame.height*0.5);
36 | self.saveIcon.image = UIImage(named: "saveIcon");
37 | self.addSubview(self.saveIcon)
38 | }
39 |
40 | override init(frame: CGRect) {
41 | super.init(frame: frame);
42 |
43 | }
44 |
45 | required init?(coder aDecoder: NSCoder) {
46 | super.init(coder: aDecoder);
47 | }
48 |
49 | func generateAttributedTitle(string:String, size:CGFloat) -> NSMutableAttributedString{
50 | return NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont(name: "Helvetica", size: size)]);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/CameraHUDViewControllerViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HiddenStatusBarViewController.swift
3 | // xArt
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/2/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ARKit
11 | import AVFoundation
12 | import Photos
13 |
14 | protocol CameraHUDDelegate {
15 | func startRecording();
16 | func stopRecording();
17 | func resetCameraHUD();
18 | func exportVideo();
19 | func endAudioSession();
20 | func saveImage(image:UIImage);
21 | func previewPhoto(image:UIImage)
22 | }
23 |
24 | class CameraHUDViewController: UIViewController, CameraHUDDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
25 |
26 | // Views
27 | var baseView: BaseView = BaseView();
28 | var previewView: PreviewView = PreviewView();
29 |
30 | // Delegates
31 | public var viewControllerDelegate:ViewControllerDelegate?;
32 | // Sceneview
33 | public var sceneView:ARSCNView = ARSCNView();
34 | private var sampleImage:UIImage?
35 | private var renderer:SCNRenderer?
36 |
37 | // Recording
38 | public var isRecording:Bool = false;
39 | var snapshotArray:[[String:Any]] = [[String:Any]]()
40 | var lastTime:TimeInterval = 0
41 | public var videoStartTime:CMTime?;
42 |
43 | // Asset Writer
44 | var pixelBufferAdaptor:AVAssetWriterInputPixelBufferAdaptor?
45 | var videoInput:AVAssetWriterInput?;
46 | var audioInput:AVAssetWriterInput?;
47 | var assetWriter:AVAssetWriter?;
48 |
49 | // Audio
50 | var captureSession: AVCaptureSession?
51 | var micInput:AVCaptureDeviceInput?
52 | var audioOutput:AVCaptureAudioDataOutput?
53 | var recordingSession:AVAudioSession!
54 |
55 | override func viewDidLoad() {
56 | super.viewDidLoad()
57 | self.intializeBasicCameraHUD();
58 | }
59 |
60 | override func didReceiveMemoryWarning() {
61 | super.didReceiveMemoryWarning()
62 | // Dispose of any resources that can be recreated.
63 | }
64 |
65 | func prefersStatusBarHidden() -> Bool {
66 | return true
67 | }
68 |
69 | // MARK: STARTING / REFRESHING FUNCTIONALITY
70 |
71 | func intializeBasicCameraHUD() {
72 | DispatchQueue.main.async {
73 | // Do any additional setup after loading the view.
74 |
75 | self.sampleImage = self.sceneView.snapshot();
76 |
77 | self.renderer = SCNRenderer(device: MTLCreateSystemDefaultDevice(), options: [:])
78 | self.renderer!.scene = self.sceneView.scene
79 | self.renderer!.pointOfView = self.sceneView.pointOfView
80 |
81 | self.baseView = BaseView(frame: self.view.frame);
82 | self.baseView.cameraHUDDelegate = self;
83 | self.baseView.viewControllerDelegate = self.viewControllerDelegate;
84 | self.baseView.sceneView = self.sceneView;
85 |
86 | self.baseView.start();
87 | self.view.addSubview(self.baseView);
88 |
89 | self.previewView = PreviewView(frame: self.view.frame);
90 | self.previewView.cameraHUDDelegate = self;
91 |
92 | artzyNotificationView = NotificationView(frame: CGRect(x: screenWidth*0.25, y: 0, width: screenWidth*0.5, height: screenHeight*0.2));
93 | self.view.addSubview(artzyNotificationView)
94 |
95 |
96 | }
97 | }
98 |
99 | public func resetCameraHUD() {
100 |
101 | self.viewControllerDelegate?.resetTracking();
102 |
103 | DispatchQueue.main.async {
104 | for view in self.view.subviews {
105 | view.removeFromSuperview();
106 | }
107 |
108 | self.intializeBasicCameraHUD();
109 | }
110 | }
111 |
112 | // MARK: DID UPDATE AT TIME
113 |
114 | let filmQueue:DispatchQueue = DispatchQueue(label: "filmQueue");
115 | var snapshot:UIImage?;
116 | let scale = CMTimeScale(NSEC_PER_SEC)
117 |
118 | public func didUpdateAtTime(time: TimeInterval) {
119 |
120 |
121 | if self.isRecording {
122 |
123 | if self.lastTime == 0 || (self.lastTime + 1/25) < time {
124 |
125 | // filmQueue.sync { [weak self] () -> Void in
126 |
127 | var currentFrameTime:CMTime = CMTime(value: CMTimeValue((self.sceneView.session.currentFrame!.timestamp) * Double(scale)), timescale: scale);
128 |
129 | if self.lastTime == 0 {
130 | self.videoStartTime = currentFrameTime;
131 | }
132 |
133 | print("[artzyhud] UPDATE AT TIME : \(time)");
134 |
135 | self.lastTime = time;
136 |
137 | // VIDEO
138 |
139 | let snapshot:UIImage = self.sceneView.snapshot()
140 |
141 | self.createPixelBufferFromUIImage(image:snapshot, completionHandler: { (error, pixelBuffer) in
142 |
143 | guard error == nil else {
144 | print("failed to get pixelBuffer");
145 | return
146 | }
147 |
148 | currentFrameTime = currentFrameTime - self.videoStartTime!;
149 |
150 |
151 | if (self.videoInput?.isReadyForMoreMediaData)! {
152 | // Add pixel buffer to video input
153 | self.pixelBufferAdaptor!.append(pixelBuffer!, withPresentationTime: currentFrameTime);
154 | return
155 | }
156 | else {
157 | print("FAILED TO PASS DATA")
158 | }
159 | });
160 |
161 | // }
162 | }
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Functionality/HUDAudioFunc.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HUDAudioFunc.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/4/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AVFoundation
11 |
12 | extension CameraHUDViewController {
13 |
14 | // MARK: AUDIO FUNCTIONALITY
15 |
16 | func startAudioRecording(completionHandler:@escaping(Bool) -> ()) {
17 |
18 | self.recordingSession = AVAudioSession.sharedInstance()
19 |
20 | do {
21 | try self.recordingSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .videoRecording, options: [.defaultToSpeaker])
22 | try self.recordingSession.setActive(true, options: .notifyOthersOnDeactivation)
23 |
24 | print("REQUESTED SESSION")
25 |
26 | self.recordingSession!.requestRecordPermission() { [unowned self] allowed in
27 | DispatchQueue.main.async {
28 | if allowed {
29 | // self.loadRecordingUI()
30 | print("SESSION ALLOWED")
31 | // let microphone = AVCaptureDevice.default(.builtInMicrophone, for: AVMediaType.audio, position: .unspecified)
32 | let microphone = AVCaptureDevice.default(.builtInMicrophone, for: AVMediaType.audio, position: .unspecified)
33 |
34 | do {
35 | try self.micInput = AVCaptureDeviceInput(device: microphone!);
36 |
37 | self.captureSession = AVCaptureSession();
38 |
39 | if (self.captureSession?.canAddInput(self.micInput!))! {
40 | self.captureSession?.addInput(self.micInput!);
41 |
42 | self.audioOutput = AVCaptureAudioDataOutput();
43 |
44 | if self.captureSession!.canAddOutput(self.audioOutput!){
45 | self.captureSession!.addOutput(self.audioOutput!)
46 | self.audioOutput?.setSampleBufferDelegate(self, queue: DispatchQueue.global());
47 |
48 | self.captureSession?.startRunning();
49 | completionHandler(true);
50 | }
51 |
52 | }
53 | }
54 | catch {
55 | completionHandler(false);
56 | }
57 | } else {
58 | // self.loadFailUI()
59 | completionHandler(false);
60 |
61 | }
62 | }
63 | }
64 | } catch {
65 | // self.loadFailUI()
66 | completionHandler(false);
67 | }
68 |
69 |
70 | }
71 |
72 | func endAudioCapture() {
73 | self.captureSession!.stopRunning();
74 | }
75 |
76 | public func endAudioSession() {
77 | do {
78 | try self.recordingSession.setActive(false, options: .notifyOthersOnDeactivation)
79 | }
80 | catch {
81 | print("ERROR CANCELLING RECORDING SESSION : \(error)")
82 | }
83 | }
84 |
85 | func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
86 |
87 | guard sampleBuffer != nil else {
88 | print("SAMPLE BUFFER EQUALS NIL ")
89 | return
90 | }
91 |
92 |
93 | // You now have the sample buffer - correct the timestamp to the video timestamp
94 |
95 | //https://github.com/takecian/video-examples-ios/blob/master/recordings/TimelapseCameraEngine.swift
96 |
97 | var count: CMItemCount = 0
98 | CMSampleBufferGetSampleTimingInfoArray(sampleBuffer, entryCount: 0, arrayToFill: nil, entriesNeededOut: &count);
99 | var info = [CMSampleTimingInfo](repeating: CMSampleTimingInfo(duration: CMTimeMake(value: 0, timescale: 0), presentationTimeStamp: CMTimeMake(value: 0, timescale: 0), decodeTimeStamp: CMTimeMake(value: 0, timescale: 0)), count: count)
100 | CMSampleBufferGetSampleTimingInfoArray(sampleBuffer, entryCount: count, arrayToFill: &info, entriesNeededOut: &count);
101 |
102 | let scale = CMTimeScale(NSEC_PER_SEC)
103 | var currentFrameTime:CMTime = CMTime(value: CMTimeValue((self.sceneView.session.currentFrame!.timestamp) * Double(scale)), timescale: scale);
104 |
105 | if self.videoStartTime == CMTime.zero {
106 | self.videoStartTime = currentFrameTime;
107 | }
108 |
109 | currentFrameTime = currentFrameTime-self.videoStartTime!;
110 |
111 | for i in 0.. Void in
47 |
48 | self.isRecording = false;
49 | self.endAudioCapture();
50 | print("ENDED RECORDING")
51 |
52 | self.finishVideoRecording { (videoURL) in
53 | print("VIDEO URL")
54 | DispatchQueue.main.sync {
55 | self.view.addSubview(self.previewView);
56 | self.view.bringSubviewToFront(artzyNotificationView);
57 | }
58 | self.previewView.showPreviewView(withURL: videoURL);
59 | }
60 |
61 | // }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Functionality/HUDVideoFunc.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewControllerReplayKitFunctionality.swift
3 | // xArt
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/2/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import AVFoundation
12 | import Photos
13 |
14 | extension CameraHUDViewController {
15 |
16 | public func saveVideo(withName:String, imageArray:[[String:Any]], fps:Int, size:CGSize) {
17 |
18 | self.createURLForVideo(withName: withName) { (videoURL) in
19 | self.prepareWriterAndInput(size:size, videoURL: videoURL, completionHandler: { (error) in
20 |
21 | guard error == nil else {
22 | // it errored.
23 | return
24 | }
25 |
26 | self.createVideo(imageArray: imageArray, fps: fps, size:size, completionHandler: { _ in
27 | print("[F] saveVideo :: DONE");
28 |
29 | guard error == nil else {
30 | // it errored.
31 | return
32 | }
33 |
34 | self.finishVideoRecordingAndSave();
35 |
36 | });
37 | });
38 | }
39 |
40 | }
41 |
42 | public func createURLForVideo(withName:String, completionHandler:@escaping (URL)->()) {
43 | // Clear the location for the temporary file.
44 | let temporaryDirectoryURL:URL = URL.init(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true);
45 | let targetURL:URL = temporaryDirectoryURL.appendingPathComponent("\(withName).mp4")
46 | // Delete the file, incase it exists.
47 | do {
48 | try FileManager.default.removeItem(at: targetURL);
49 |
50 | } catch let error {
51 | NSLog("Unable to delete file, with error: \(error)")
52 | }
53 | // return the URL
54 | completionHandler(targetURL);
55 | }
56 |
57 | public func prepareWriterAndInput(size:CGSize, videoURL:URL, completionHandler:@escaping(Error?)->()) {
58 |
59 | do {
60 | self.assetWriter = try AVAssetWriter(outputURL: videoURL, fileType: AVFileType.mp4)
61 |
62 | // Input is the mic audio of the AVAudioEngine
63 | let audioOutputSettings = [
64 | AVFormatIDKey : kAudioFormatMPEG4AAC,
65 | AVNumberOfChannelsKey : 2,
66 | AVSampleRateKey : 44100.0,
67 | AVEncoderBitRateKey: 192000
68 | ] as [String : Any]
69 |
70 | self.audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: audioOutputSettings);
71 | self.audioInput!.expectsMediaDataInRealTime = true
72 | self.assetWriter?.add(self.audioInput!);
73 |
74 | // self.audioInput.
75 |
76 | // Video Input Creator
77 |
78 | let videoOutputSettings: Dictionary = [
79 | AVVideoCodecKey : AVVideoCodecType.h264,
80 | AVVideoWidthKey : size.width,
81 | AVVideoHeightKey : size.height
82 | ];
83 |
84 | self.videoInput = AVAssetWriterInput (mediaType: AVMediaType.video, outputSettings: videoOutputSettings)
85 | self.videoInput!.expectsMediaDataInRealTime = true
86 | self.assetWriter!.add(self.videoInput!)
87 |
88 | // Create Pixel buffer Adaptor
89 |
90 | let sourceBufferAttributes:[String : Any] = [
91 | (kCVPixelBufferPixelFormatTypeKey as String): Int(kCVPixelFormatType_32ARGB),
92 | (kCVPixelBufferWidthKey as String): Float(size.width),
93 | (kCVPixelBufferHeightKey as String): Float(size.height)] as [String : Any]
94 |
95 | self.pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: self.videoInput!, sourcePixelBufferAttributes: sourceBufferAttributes);
96 |
97 | self.assetWriter?.startWriting();
98 | self.assetWriter?.startSession(atSourceTime: CMTime.zero);
99 | completionHandler(nil);
100 | }
101 | catch {
102 | print("Failed to create assetWritter with error : \(error)");
103 | completionHandler(error);
104 | }
105 | }
106 |
107 | private func createVideo(imageArray:[[String:Any]], fps:Int, size:CGSize, completionHandler:@escaping(String?)->()) {
108 |
109 | var currentframeTime:CMTime = CMTime.zero;
110 | var currentFrame:Int = 0;
111 |
112 | let startTime:CMTime = (imageArray[0])["time"] as! CMTime;
113 |
114 | while (currentFrame < imageArray.count) {
115 |
116 | // When the video input is ready for more media data...
117 | if (self.videoInput?.isReadyForMoreMediaData)! {
118 | print("processing current frame :: \(currentFrame)");
119 | // Get current UI Image
120 | let currentImage:UIImage = (imageArray[currentFrame])["image"] as! UIImage;
121 |
122 | // Create the pixel buffer
123 | self.createPixelBufferFromUIImage(image: currentImage) { (error, pixelBuffer) in
124 |
125 | guard error == nil else {
126 | completionHandler("failed to get pixelBuffer");
127 | return
128 | }
129 |
130 | // Calc the current frame time
131 | currentframeTime = (imageArray[currentFrame])["time"] as! CMTime - startTime;
132 | print("SECONDS : \(currentframeTime.seconds)")
133 | print("Current frame time :: \(currentframeTime)");
134 |
135 | // Add pixel buffer to video input
136 | self.pixelBufferAdaptor!.append(pixelBuffer!, withPresentationTime: currentframeTime);
137 |
138 | // increment frame
139 | currentFrame += 1;
140 | }
141 | }
142 | }
143 |
144 | // FINISHED
145 | completionHandler(nil);
146 | }
147 |
148 |
149 | public func createPixelBufferFromCGImage(image:CGImage, completionHandler:@escaping(String?, CVPixelBuffer?) -> ()) {
150 | //https://stackoverflow.com/questions/44400741/convert-image-to-cvpixelbuffer-for-machine-learning-swift
151 | let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
152 | var pixelBuffer : CVPixelBuffer?
153 | let status = CVPixelBufferCreate(kCFAllocatorDefault, image.width, image.height, kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
154 | guard (status == kCVReturnSuccess) else {
155 | completionHandler("Failed to create pixel buffer", nil)
156 | return
157 | }
158 |
159 | CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
160 | let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
161 |
162 | let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
163 | let context = CGContext(data: pixelData, width: image.width, height: image.height, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
164 |
165 | context?.translateBy(x: 0, y: CGFloat(image.height))
166 | context?.scaleBy(x: 1.0, y: -1.0)
167 |
168 | // UIGraphicsPushContext(context!)
169 | // image.draw(in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
170 | // UIGraphicsPopContext()
171 | // context.draw(image, in: CGRect(x: 0.0,y: 0.0,width: image.width, height: image.height));
172 | // context?.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height));
173 |
174 | UIGraphicsPushContext(context!)
175 | context?.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height));
176 | UIGraphicsPopContext()
177 |
178 | CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
179 |
180 | completionHandler(nil, pixelBuffer)
181 | }
182 |
183 | public func createPixelBufferFromUIImage(image:UIImage, completionHandler:@escaping(String?, CVPixelBuffer?) -> ()) {
184 | //https://stackoverflow.com/questions/44400741/convert-image-to-cvpixelbuffer-for-machine-learning-swift
185 | let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
186 | var pixelBuffer : CVPixelBuffer?
187 | let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(UIScreen.main.bounds.size.width), Int(UIScreen.main.bounds.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
188 |
189 | guard (status == kCVReturnSuccess) else {
190 | completionHandler("Failed to create pixel buffer", nil)
191 | return
192 | }
193 |
194 | CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
195 | let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
196 |
197 | let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
198 | let context = CGContext(data: pixelData, width: Int(UIScreen.main.bounds.size.width), height: Int(UIScreen.main.bounds.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
199 |
200 | context?.translateBy(x: 0, y: UIScreen.main.bounds.size.height)
201 | context?.scaleBy(x: 1.0, y: -1.0)
202 |
203 | UIGraphicsPushContext(context!)
204 | image.draw(in: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
205 | UIGraphicsPopContext()
206 | CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
207 |
208 | // CVPixelBufferReleaseBytesCallback(
209 |
210 | completionHandler(nil, pixelBuffer)
211 | }
212 |
213 |
214 | public func finishVideoRecordingAndSave() {
215 | self.videoInput!.markAsFinished();
216 | self.audioInput?.markAsFinished();
217 | self.assetWriter?.finishWriting(completionHandler: {
218 | print("output url : \(self.assetWriter?.outputURL)");
219 |
220 | PHPhotoLibrary.requestAuthorization({ (status) in
221 | PHPhotoLibrary.shared().performChanges({
222 | PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: (self.assetWriter?.outputURL)!)
223 | }) { saved, error in
224 |
225 | guard error == nil else {
226 | print("failed to save video");
227 | print("error : \(error)")
228 | return
229 | }
230 |
231 | if saved {
232 | let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
233 | let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
234 | alertController.addAction(defaultAction)
235 | self.present(alertController, animated: true, completion: nil)
236 | }
237 |
238 | self.snapshotArray.removeAll();
239 | FileManager.default.clearTmpDirectory();
240 | }
241 | })
242 | })
243 | }
244 |
245 | public func finishVideoRecording(completionHandler:@escaping(URL)->()) {
246 | self.videoInput!.markAsFinished();
247 | self.audioInput?.markAsFinished();
248 | self.assetWriter?.finishWriting(completionHandler: {
249 | print("output url : \(self.assetWriter?.outputURL)");
250 |
251 | completionHandler((self.assetWriter?.outputURL)!);
252 | })
253 | }
254 |
255 | public func exportVideo() {
256 | PHPhotoLibrary.requestAuthorization({ (status) in
257 | PHPhotoLibrary.shared().performChanges({
258 | PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: (self.assetWriter?.outputURL)!)
259 | }) { saved, error in
260 |
261 | guard error == nil else {
262 | print("failed to save video");
263 | print("error : \(error)")
264 | return
265 | }
266 |
267 | if saved {
268 | let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
269 | let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
270 | alertController.addAction(defaultAction)
271 | self.present(alertController, animated: true, completion: nil)
272 | }
273 |
274 | self.videoInput = nil;
275 | self.pixelBufferAdaptor = nil;
276 | self.audioInput = nil;
277 | self.assetWriter = nil;
278 |
279 | FileManager.default.clearTmpDirectory();
280 | }
281 | })
282 | }
283 |
284 | }
285 |
286 |
287 | extension FileManager {
288 | func clearTmpDirectory() {
289 | do {
290 | let tmpDirURL = FileManager.default.temporaryDirectory
291 | let tmpDirectory = try contentsOfDirectory(atPath: tmpDirURL.path)
292 | try tmpDirectory.forEach { file in
293 | let fileUrl = tmpDirURL.appendingPathComponent(file)
294 | try removeItem(atPath: fileUrl.path)
295 | }
296 | } catch {
297 | //catch the error somehow
298 | }
299 | }
300 | }
301 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/NotificationView/NotificationBlimp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationBlimp.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/4/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class NotificationBlimp: UIView {
13 |
14 | let flash = CABasicAnimation(keyPath: "opacity")
15 | var previousState:ArtzyNotificationStyle = .searching;
16 |
17 | override init(frame: CGRect) {
18 | super.init(frame: frame);
19 | self.layer.backgroundColor = UIColor.white.cgColor;
20 | self.layer.cornerRadius = self.frame.width/2;
21 | }
22 |
23 | required init?(coder aDecoder: NSCoder) {
24 | super.init(coder: aDecoder);
25 | }
26 |
27 | public func updateNotificationStyle(style:ArtzyNotificationStyle) {
28 |
29 | print("STYLE : \(style)")
30 |
31 | switch style {
32 | case .searching:
33 | self.previousState = .searching
34 | self.blink()
35 | break
36 | case .preview:
37 | self.hide()
38 | break
39 | case .itemFound:
40 | self.previousState = .itemFound
41 | self.greenLight()
42 | break
43 | case .error:
44 | self.previousState = .error
45 | self.redLight()
46 | break
47 | case .previous:
48 | self.updateNotificationStyle(style: self.previousState)
49 | break
50 | default:
51 | // Error
52 | break
53 | }
54 |
55 | }
56 |
57 | private func redLight() {
58 | self.removeBlink();
59 | self.alpha = 1;
60 | self.layer.backgroundColor = UIColor.red.cgColor;
61 | }
62 |
63 | private func greenLight() {
64 | self.removeBlink();
65 | self.alpha = 1;
66 | self.layer.backgroundColor = UIColor.green.cgColor;
67 | }
68 |
69 | private func hide() {
70 | self.removeBlink();
71 | self.alpha = 0;
72 | }
73 |
74 |
75 |
76 | private func blink() {
77 | self.alpha = 1;
78 |
79 | flash.duration = 1.33
80 | flash.fromValue = 1 // alpha
81 | flash.toValue = 0 // alpha
82 | flash.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
83 | flash.autoreverses = true
84 | flash.repeatCount = HUGE;
85 |
86 | layer.add(flash, forKey: nil)
87 | }
88 |
89 | private func removeBlink() {
90 | layer.removeAllAnimations()
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/NotificationView/NotificationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationBarView.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/4/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import AVFoundation
12 |
13 | enum ArtzyNotificationStyle {
14 | case searching
15 | case itemFound
16 | case preview
17 | case error
18 | case previous
19 | }
20 |
21 | class NotificationView: UIView {
22 |
23 | public var title:String = "searching...";
24 | private var previousTitle:String = "";
25 | private var notificationLabel:UILabel = UILabel();
26 |
27 |
28 |
29 | override init(frame: CGRect) {
30 | super.init(frame: frame);
31 |
32 | artzyNotificationBlimp = NotificationBlimp(frame: kArtzyBlimpBaseRect);
33 | self.addSubview(artzyNotificationBlimp)
34 |
35 | self.notificationLabel.frame = kArtzyNotificationLabelRect;
36 | self.updateNotification(title: self.title, style:.searching);
37 |
38 | self.addSubview(self.notificationLabel);
39 | }
40 |
41 | required init?(coder aDecoder: NSCoder) {
42 | super.init(coder: aDecoder);
43 | }
44 |
45 | func generateAttributedTitle(string:String, size:CGFloat) -> NSMutableAttributedString{
46 | return NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont(name: "Helvetica", size: size)]);
47 | }
48 |
49 |
50 | // Update Title
51 |
52 | public func updateNotification(title:String, style:ArtzyNotificationStyle) {
53 |
54 | self.previousTitle = self.title;
55 | self.title = title;
56 |
57 | self.notificationLabel.attributedText = self.generateAttributedTitle(string: self.title, size: 18)
58 | self.notificationLabel.numberOfLines = 3
59 |
60 | self.notificationLabel.textAlignment = .center;
61 | self.notificationLabel.frame = kArtzyNotificationLabelRect
62 | self.notificationLabel.sizeToFit();
63 |
64 | self.notificationLabel.frame = CGRect(x: kArtzyNotificationLabelRect.minX, y: kArtzyNotificationLabelRect.minY, width: kArtzyNotificationLabelRect.width, height: self.notificationLabel.frame.height)
65 |
66 | artzyNotificationBlimp.updateNotificationStyle(style:style);
67 | }
68 |
69 | public func returnToPreviousTitle() {
70 | self.title = self.previousTitle;
71 |
72 | self.notificationLabel.attributedText = self.generateAttributedTitle(string: self.title, size: 18)
73 | self.notificationLabel.numberOfLines = 3
74 |
75 | self.notificationLabel.textAlignment = .center;
76 | self.notificationLabel.frame = kArtzyNotificationLabelRect
77 | self.notificationLabel.sizeToFit();
78 | self.notificationLabel.frame = CGRect(x: kArtzyNotificationLabelRect.minX, y: kArtzyNotificationLabelRect.minY, width: kArtzyNotificationLabelRect.width, height: self.notificationLabel.frame.height)
79 |
80 | artzyNotificationBlimp.updateNotificationStyle(style:.previous);
81 | }
82 |
83 | public func makeNotificationBlink() {
84 |
85 |
86 | }
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/ArtzyCamera/HUD/Preview/PreviewView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreviewView.swift
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import AVFoundation
12 |
13 | enum ArtzyPreviewTypes {
14 | case image
15 | case video
16 | }
17 |
18 | class PreviewView: UIView {
19 |
20 | public var cameraHUDDelegate:CameraHUDDelegate?
21 |
22 | private var previewType:ArtzyPreviewTypes = .image;
23 |
24 | private var imageView:UIImageView = UIImageView()
25 | private var previewImage:UIImage = UIImage();
26 |
27 | private var player:AVPlayer?
28 | private var playerLayer:AVPlayerLayer?
29 | private var videoURL:URL?
30 |
31 | private var saveButton:SaveButton = SaveButton();
32 | private var cancelButton:CancelButton = CancelButton();
33 |
34 | override init(frame: CGRect) {
35 | super.init(frame: frame);
36 |
37 | self.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight);
38 |
39 | self.imageView.frame = self.frame;
40 |
41 | // Save button
42 | // let saveButtonWidth:CGFloat = screenWidth/4;
43 | // let saveButtonHeight:CGFloat = screenHeight/15;
44 | // self.saveButton.frame = CGRect(x: screenWidth - saveButtonWidth - kArtzyHUDButtonGap/2, y: (screenHeight*0.7-saveButtonHeight), width: saveButtonWidth, height: saveButtonHeight);
45 | // self.saveButton.setAttributedTitle(self.generateAttributedTitle(string: "save", size:18), for: .normal);
46 | self.saveButton.addTarget(self, action: #selector(self.saveButtonPressed), for: .touchUpInside);
47 |
48 | // Cancel button
49 | // SAME AS RESET BUTTON
50 | // self.cancelButton.frame = CGRect(x: kArtzyHUDButtonGap/2, y:kArtzyResetButtonMinY, width: kArtzyResetButtonDimension*1.25, height: kArtzyResetButtonDimension);
51 | // self.cancelButton.setAttributedTitle(self.generateAttributedTitle(string: "cancel", size:18), for: .normal);
52 | self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), for: .touchUpInside);
53 |
54 | // Loop Observer
55 | NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: self.player?.currentItem, queue: .main) { _ in
56 | self.player?.seek(to: CMTime.zero)
57 | self.player?.play()
58 | }
59 | }
60 |
61 | required init?(coder aDecoder: NSCoder) {
62 | super.init(coder: aDecoder);
63 | }
64 |
65 | func generateAttributedTitle(string:String, size:CGFloat) -> NSMutableAttributedString{
66 | return NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont(name: "Helvetica", size: size)]);
67 | }
68 |
69 | public func showPreviewView(withImage:UIImage) {
70 | self.previewType = .image;
71 |
72 | DispatchQueue.main.async {
73 | self.imageView.image = withImage;
74 | self.addSubview(self.imageView);
75 |
76 | // Add Buttons
77 | self.addSubview(self.saveButton);
78 | self.addSubview(self.cancelButton);
79 | artzyNotificationView.updateNotification(title: "preview", style: .preview);
80 | }
81 |
82 | // DispatchQueue.main.sync {
83 | // artzyNotificationView.updateNotification(title: "preview", style: .preview);
84 | // }
85 | }
86 |
87 | public func showPreviewView(withURL:URL) {
88 |
89 | self.previewType = .video;
90 |
91 | self.videoURL = withURL;
92 | self.createPreviewVideo();
93 |
94 | DispatchQueue.main.sync {
95 | artzyNotificationView.updateNotification(title: "preview", style: .preview);
96 | }
97 | }
98 |
99 | private func hidePreviewView() {
100 |
101 | self.removePreview();
102 | self.removeFromSuperview();
103 |
104 | if self.previewType == .video {
105 | self.cameraHUDDelegate?.endAudioSession();
106 | }
107 | }
108 |
109 | private func createPreviewVideo() {
110 |
111 | guard self.videoURL != nil else {
112 | print("No video url")
113 | return
114 | }
115 |
116 | self.player = AVPlayer(url: self.videoURL!);
117 |
118 | guard self.player != nil else {
119 | print("Failed to create player")
120 | return
121 | }
122 |
123 | self.playerLayer = AVPlayerLayer();
124 | self.playerLayer? = AVPlayerLayer(player: self.player);
125 | self.playerLayer?.frame = self.frame;
126 |
127 | guard self.playerLayer != nil else {
128 | print("Failed to create player layer")
129 | return
130 | }
131 |
132 |
133 |
134 |
135 | // Bring buttons to front
136 | DispatchQueue.main.async {
137 | // Add Player Layer
138 | self.layer.addSublayer(self.playerLayer!);
139 | // Add Buttons
140 | self.addSubview(self.saveButton);
141 | self.addSubview(self.cancelButton);
142 | self.player!.play();
143 | }
144 |
145 |
146 |
147 | }
148 |
149 |
150 | // MARK : BUTTON FUNCTIONALITY
151 |
152 | @objc private func saveButtonPressed() {
153 |
154 | if self.previewType == .video {
155 | self.cameraHUDDelegate?.exportVideo();
156 | }
157 | else {
158 | self.cameraHUDDelegate?.saveImage(image: self.imageView.image!)
159 | }
160 |
161 | self.hidePreviewView();
162 | }
163 |
164 | @objc private func cancelButtonPressed() {
165 | print("CANCEL BUTTON PRESSED");
166 | self.hidePreviewView();
167 | FileManager.default.clearTmpDirectory();
168 | }
169 |
170 | // MARK : COMMON FUNCTIONALITY
171 |
172 | private func removePreview() {
173 |
174 | // Video
175 |
176 | self.player?.pause();
177 | self.playerLayer?.removeFromSuperlayer();
178 |
179 | self.player = nil;
180 | self.playerLayer = nil;
181 |
182 | self.saveButton.removeFromSuperview();
183 | self.cancelButton.removeFromSuperview();
184 |
185 | // Image
186 |
187 | self.imageView.image = nil;
188 | self.imageView.removeFromSuperview();
189 |
190 | // Notification
191 |
192 | artzyNotificationView.returnToPreviousTitle();
193 |
194 | }
195 |
196 |
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/ArtzyCamera/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 | NSCameraUsageDescription
24 | This application will use the camera for Augmented Reality.
25 | NSLocationWhenInUseUsageDescription
26 | This application will use location for Augmented Reality.
27 | NSMicrophoneUsageDescription
28 | This application will use the camera to record Augmented Reality.
29 | NSPhotoLibraryAddUsageDescription
30 | This application will use the Photo Library to save media.
31 | NSPhotoLibraryUsageDescription
32 | This application will use the Photo Library to save media.
33 | UIMainStoryboardFile
34 | Main
35 | UIRequiredDeviceCapabilities
36 |
37 | armv7
38 | arkit
39 |
40 | UIRequiresFullScreen
41 |
42 | UIStatusBarHidden
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 |
48 | UISupportedInterfaceOrientations~ipad
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationPortraitUpsideDown
52 | UIInterfaceOrientationLandscapeLeft
53 | UIInterfaceOrientationLandscapeRight
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Functionality/ShaderFunctionality.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShaderFunctionality.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import ARKit
11 |
12 | extension PieceOfArtzy {
13 |
14 | // MARK: SHADERS
15 |
16 | func addColorShaderForChild(child: SCNNode, red:Float, blue:Float, green:Float) {
17 | let program = SCNProgram()
18 | var programType:String = "Color"
19 | program.fragmentFunctionName = programType+"SurfaceFragment"
20 | program.vertexFunctionName = programType+"VertexShader"
21 | program.isOpaque = false;
22 |
23 | // CREATE A MATERIAL, ADD THE PROGRAM, AND ADD IT TO THE CHILD.
24 | let shaderMaterial = SCNMaterial()
25 | shaderMaterial.program = program;
26 | shaderMaterial.transparencyMode = .rgbZero;
27 | shaderMaterial.isDoubleSided = true;
28 | shaderMaterial.blendMode = .alpha;
29 | shaderMaterial.writesToDepthBuffer = false
30 | shaderMaterial.readsFromDepthBuffer = false
31 | shaderMaterial.cullMode = .back
32 | shaderMaterial.lightingModel = .lambert;
33 |
34 | var TimeVariables:timedShaderVariablesStruct = timedShaderVariablesStruct.init(loopTime: 10, startTime: 0, endTime: 0, colorR:red, colorB:blue, colorG:green);
35 | shaderMaterial.setValue(Data(bytes: &TimeVariables, count: MemoryLayout.stride), forKey: "timeVariables");
36 |
37 | child.geometry?.materials = [shaderMaterial];
38 | }
39 |
40 | func addTextureShaderForChild(child: SCNNode, texture:UIImage) {
41 | let program = SCNProgram()
42 | var programType:String = "Texture"
43 | program.fragmentFunctionName = programType+"SurfaceFragment"
44 | program.vertexFunctionName = programType+"VertexShader"
45 | program.isOpaque = false;
46 |
47 | // CREATE A MATERIAL, ADD THE PROGRAM, AND ADD IT TO THE CHILD.
48 | let shaderMaterial = SCNMaterial()
49 | shaderMaterial.program = program;
50 | shaderMaterial.transparencyMode = .rgbZero;
51 | shaderMaterial.isDoubleSided = false;
52 | shaderMaterial.blendMode = .alpha;
53 | shaderMaterial.writesToDepthBuffer = true
54 | shaderMaterial.readsFromDepthBuffer = true
55 | shaderMaterial.cullMode = .back
56 | shaderMaterial.lightingModel = .lambert;
57 |
58 | let imageProperty = SCNMaterialProperty(contents: texture)
59 | shaderMaterial.setValue(imageProperty, forKey: "diffuseTexture")
60 |
61 | // var TimeVariables:timedShaderVariablesStruct = timedShaderVariablesStruct.init(loopTime: 10, startTime: 0, endTime: 0, colorR:red, colorB:blue, colorG:green);
62 | // shaderMaterial.setValue(Data(bytes: &TimeVariables, count: MemoryLayout.stride), forKey: "timeVariables");
63 |
64 | child.geometry?.materials = [shaderMaterial];
65 | }
66 |
67 | func addTimedStrokeShaderWithTimeForChild(child:SCNNode, loopTime:Float, startTime:Float, endTime:Float) {
68 |
69 |
70 | DispatchQueue.main.async {
71 | let program = SCNProgram()
72 | let programType:String = "TimedStroke"
73 |
74 |
75 | program.fragmentFunctionName = programType+"SurfaceFragment"
76 | program.vertexFunctionName = programType+"VertexShader"
77 |
78 | program.isOpaque = false;
79 |
80 | let shaderMaterial = SCNMaterial();
81 | shaderMaterial.program = program;
82 | shaderMaterial.transparencyMode = .rgbZero;
83 | shaderMaterial.blendMode = .alpha;
84 | shaderMaterial.writesToDepthBuffer = false
85 | shaderMaterial.readsFromDepthBuffer = false
86 | shaderMaterial.cullMode = .back
87 |
88 | var firstStrokeTimeVariableStruct:strokeTimeVariableStruct = strokeTimeVariableStruct.init(loopTime: loopTime, startTime: startTime, endTime: endTime);
89 | shaderMaterial.setValue(Data(bytes: &firstStrokeTimeVariableStruct, count: MemoryLayout.stride), forKey: "timeVariables");
90 |
91 | child.geometry?.materials = [shaderMaterial];
92 | }
93 | }
94 |
95 | func addBackwardsTimedStrokeShaderWithTimeForChild(child:SCNNode, loopTime:Float, startTime:Float, endTime:Float) {
96 |
97 |
98 | DispatchQueue.main.async {
99 | let program = SCNProgram()
100 | let programType:String = "BackwardsTimedStroke"
101 |
102 |
103 | program.fragmentFunctionName = programType+"SurfaceFragment"
104 | program.vertexFunctionName = programType+"VertexShader"
105 |
106 | program.isOpaque = false;
107 |
108 | let shaderMaterial = SCNMaterial();
109 | shaderMaterial.program = program;
110 | shaderMaterial.transparencyMode = .rgbZero;
111 | shaderMaterial.blendMode = .alpha;
112 | shaderMaterial.writesToDepthBuffer = false
113 | shaderMaterial.readsFromDepthBuffer = false
114 | shaderMaterial.cullMode = .back
115 |
116 | var firstStrokeTimeVariableStruct:strokeTimeVariableStruct = strokeTimeVariableStruct.init(loopTime: loopTime, startTime: startTime, endTime: endTime);
117 | shaderMaterial.setValue(Data(bytes: &firstStrokeTimeVariableStruct, count: MemoryLayout.stride), forKey: "timeVariables");
118 |
119 | child.geometry?.materials = [shaderMaterial];
120 | }
121 | }
122 |
123 | func addTimedStrokeTextureShaderWithTimeForChild(child:SCNNode, loopTime:Float, startTime:Float, endTime:Float) {
124 |
125 |
126 | DispatchQueue.main.async {
127 | let program = SCNProgram()
128 | let programType:String = "TimedStrokeTexture"
129 |
130 |
131 | program.fragmentFunctionName = programType+"SurfaceFragment"
132 | program.vertexFunctionName = programType+"VertexShader"
133 |
134 | program.isOpaque = false;
135 |
136 | let shaderMaterial = SCNMaterial();
137 | shaderMaterial.program = program;
138 | shaderMaterial.transparencyMode = .rgbZero;
139 | shaderMaterial.blendMode = .alpha;
140 | shaderMaterial.writesToDepthBuffer = false
141 | shaderMaterial.readsFromDepthBuffer = false
142 | shaderMaterial.cullMode = .back
143 |
144 | var firstStrokeTimeVariableStruct:strokeTimeVariableStruct = strokeTimeVariableStruct.init(loopTime: loopTime, startTime: startTime, endTime: endTime);
145 | shaderMaterial.setValue(Data(bytes: &firstStrokeTimeVariableStruct, count: MemoryLayout.stride), forKey: "timeVariables");
146 |
147 | child.geometry?.materials = [shaderMaterial];
148 | }
149 | }
150 |
151 | func addBackwardsTimedStrokeTextureShaderWithTimeForChild(child:SCNNode, texture:UIImage, loopTime:Float, startTime:Float, endTime:Float) {
152 |
153 |
154 | DispatchQueue.main.async {
155 | let program = SCNProgram()
156 | let programType:String = "BackwardsTimedStrokeTexture"
157 |
158 |
159 | program.fragmentFunctionName = programType+"SurfaceFragment"
160 | program.vertexFunctionName = programType+"VertexShader"
161 |
162 | program.isOpaque = false;
163 |
164 | let shaderMaterial = SCNMaterial();
165 | shaderMaterial.program = program;
166 | shaderMaterial.transparencyMode = .rgbZero;
167 | shaderMaterial.blendMode = .alpha;
168 | shaderMaterial.writesToDepthBuffer = true
169 | shaderMaterial.readsFromDepthBuffer = true
170 | shaderMaterial.cullMode = .back
171 | // shaderMaterial.diffuse.contents? = texture;
172 | shaderMaterial.lightingModel = .lambert;
173 |
174 | let imageProperty = SCNMaterialProperty(contents: texture)
175 | // The name you supply here should match the texture parameter name in the fragment shader
176 | shaderMaterial.setValue(imageProperty, forKey: "diffuseTexture")
177 |
178 | var firstStrokeTimeVariableStruct:strokeTimeVariableStruct = strokeTimeVariableStruct.init(loopTime: loopTime, startTime: startTime, endTime: endTime);
179 | shaderMaterial.setValue(Data(bytes: &firstStrokeTimeVariableStruct, count: MemoryLayout.stride), forKey: "timeVariables");
180 |
181 | child.geometry?.materials = [shaderMaterial];
182 | }
183 | }
184 |
185 | func getShaderMaterialWithTitle(title:String) -> SCNMaterial {
186 |
187 | let program = SCNProgram()
188 |
189 | program.fragmentFunctionName = title+"SurfaceFragment"
190 | program.vertexFunctionName = title+"VertexShader"
191 |
192 | program.isOpaque = false;
193 |
194 | let shaderMaterial = SCNMaterial();
195 | shaderMaterial.program = program;
196 | shaderMaterial.transparencyMode = .rgbZero;
197 | shaderMaterial.blendMode = .alpha;
198 | shaderMaterial.writesToDepthBuffer = false
199 | shaderMaterial.readsFromDepthBuffer = false
200 | shaderMaterial.cullMode = .back
201 |
202 | return shaderMaterial
203 | }
204 |
205 | func addTimedVariablesToShaderWithNameAndChild(programName:String, child:SCNNode, loopTime:Float, startTime:Float, endTime:Float, colorR:Float, colorB:Float, colorG:Float) {
206 |
207 |
208 | DispatchQueue.main.async {
209 | let program = SCNProgram();
210 |
211 |
212 | program.fragmentFunctionName = programName+"SurfaceFragment"
213 | program.vertexFunctionName = programName+"VertexShader"
214 |
215 | program.isOpaque = false;
216 |
217 | let shaderMaterial = SCNMaterial();
218 | shaderMaterial.program = program;
219 | shaderMaterial.transparencyMode = .rgbZero;
220 | shaderMaterial.blendMode = .alpha;
221 | shaderMaterial.writesToDepthBuffer = true
222 | shaderMaterial.readsFromDepthBuffer = true
223 | shaderMaterial.cullMode = .back
224 |
225 | var timedShaderVariables:timedShaderVariablesStruct = timedShaderVariablesStruct.init(loopTime: loopTime, startTime: startTime, endTime: endTime, colorR: colorR, colorB: colorB, colorG: colorG)
226 | shaderMaterial.setValue(Data(bytes: &timedShaderVariables, count: MemoryLayout.stride), forKey: "timedShaderVariables");
227 |
228 | child.geometry?.materials = [shaderMaterial];
229 | }
230 | }
231 |
232 |
233 | func addStrokeShaderWithTimeForChild(child:SCNNode, loopTime:Float, startTime:Float, endTime:Float) {
234 |
235 |
236 | let program = SCNProgram()
237 | var programType:String = "TimedStroke"
238 |
239 |
240 | program.fragmentFunctionName = programType+"SurfaceFragment"
241 | program.vertexFunctionName = programType+"VertexShader"
242 |
243 | program.isOpaque = false;
244 |
245 | let shaderMaterial = SCNMaterial();
246 | shaderMaterial.program = program;
247 | shaderMaterial.transparencyMode = .rgbZero;
248 | shaderMaterial.blendMode = .alpha;
249 | shaderMaterial.writesToDepthBuffer = false
250 | shaderMaterial.readsFromDepthBuffer = false
251 | shaderMaterial.cullMode = .back
252 |
253 | var firstStrokeTimeVariableStruct:strokeTimeVariableStruct = strokeTimeVariableStruct.init(loopTime: loopTime, startTime: startTime, endTime: endTime);
254 | //strokeTimeVariableStruct(loopTime: loopTime, startTime: startTime, endTime: endTime);
255 | shaderMaterial.setValue(Data(bytes: &firstStrokeTimeVariableStruct, count: MemoryLayout.stride), forKey: "timeVariables");
256 |
257 | child.geometry?.materials = [shaderMaterial];
258 | }
259 |
260 | }
261 |
262 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/PieceOfArtzy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArtzyItem.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import ARKit
12 |
13 | class PieceOfArtzy: NSObject, UITextFieldDelegate {
14 |
15 | public var node:SCNNode?;
16 | public var referenceImage:ARReferenceImage?;
17 | public var sceneView:ARSCNView?;
18 | public var artzyHUD:UIWindow?;
19 |
20 |
21 | public var isWithinFieldOfView:Bool = false;
22 | public var weight:Float = 0;
23 | public var offset:Float = 0;
24 | public var distanceToCamera:Float = 0;
25 | public let glowModifierView:UIView = UIView();
26 |
27 | public func start() {
28 |
29 | DispatchQueue.main.sync {
30 | artzyNotificationView.updateNotification(title: "displaying \(self.referenceImage!.name!)", style: .itemFound);
31 | }
32 |
33 | if self.referenceImage!.name == "local by adamfu x delasign"{
34 | // self.performAdamLocalStroke()
35 | self.performAdamLocalStatic()
36 | }
37 |
38 | else if self.referenceImage!.name == "artzy loader by delasign"{
39 | self.performLoaderStroke();
40 | }
41 | else if self.referenceImage!.name == "hand by delasign" {
42 | let scn:SCNScene? = SCNScene(named: "art.scnassets/hand.dae");
43 | for child in scn!.rootNode.childNodes {
44 | self.node!.addChildNode(child)
45 | }
46 |
47 |
48 | scn?.rootNode.enumerateHierarchy({ (child, _) in
49 | print("Child : ", child);
50 | for key in child.animationKeys {
51 | print("KEY : ", key);
52 | let animation = child.animationPlayer(forKey: key)?.animation;
53 | animation?.repeatCount = CGFloat(HUGE);
54 | animation?.isRemovedOnCompletion = false;
55 | self.sceneView!.scene.rootNode.addAnimation(animation!, forKey: key);
56 | print(animation!)
57 | }
58 | })
59 | }
60 |
61 |
62 |
63 | }
64 | var show:Float = 0;
65 |
66 | public func didUpdateAtTime() {
67 | self.show += 0.01
68 |
69 | if self.show > 1 {
70 | self.show = 0;
71 | }
72 |
73 | if self.referenceImage!.name == "artzy loader by delasign"{
74 |
75 | let distance = simd_distance(self.node!.simdTransform.columns.3, (self.sceneView!.session.currentFrame?.camera.transform.columns.3)!);
76 |
77 | // Update distance to camera
78 | self.sceneView!.technique?.setObject(NSNumber(value: distance), forKeyedSubscript: "distanceSymbol" as NSCopying);
79 |
80 | for child in (self.node?.childNodes)! {
81 |
82 | let shaderMaterial:SCNMaterial = (child.geometry?.firstMaterial)!;
83 |
84 | // Update what should be shown of the model
85 | var displayVariables:DisplayVariableStruct = DisplayVariableStruct(show: self.show)
86 | shaderMaterial.setValue(Data(bytes: &displayVariables, count: MemoryLayout.stride), forKey: "displayVariables");
87 |
88 |
89 | }
90 |
91 | }
92 | }
93 |
94 |
95 |
96 | public func setIsWithinFieldOfView(bool:Bool){
97 | self.isWithinFieldOfView = bool;
98 |
99 | if bool {
100 | // VISIBLE
101 | self.showArtzyPieceHUD();
102 | }
103 | else {
104 | // INVISIBLE
105 | self.hideArtzyPieceHUD()
106 | }
107 | }
108 |
109 | public func showArtzyPieceHUD() {
110 |
111 | }
112 |
113 | public func hideArtzyPieceHUD() {
114 |
115 | }
116 |
117 | // MARK : CREATOR TOOLS
118 |
119 | func showDetectionPlane() {
120 | // Create a plane to visualize the initial position of the detected image.
121 | let plane = SCNPlane(width: self.referenceImage!.physicalSize.width,
122 | height: self.referenceImage!.physicalSize.height)
123 |
124 | let planeNode = SCNNode(geometry: plane)
125 | planeNode.opacity = 0.25
126 |
127 | /*
128 | `SCNPlane` is vertically oriented in its local coordinate space, but
129 | `ARImageAnchor` assumes the image is horizontal in its local space, so
130 | rotate the plane to match.
131 | */
132 | planeNode.eulerAngles.x = -.pi / 2
133 |
134 | /*
135 | Image anchors are not tracked after initial detection, so create an
136 | animation that limits the duration for which the plane visualization appears.
137 | */
138 | planeNode.runAction(self.imageHighlightAction)
139 |
140 | // Add the plane visualization to the scene.
141 | self.node!.addChildNode(planeNode)
142 | }
143 |
144 | var imageHighlightAction: SCNAction {
145 | return .sequence([
146 | .wait(duration: 0.25),
147 | .fadeOpacity(to: 0.85, duration: 0.25),
148 | .fadeOpacity(to: 0.15, duration: 0.25),
149 | .fadeOpacity(to: 0.85, duration: 0.25),
150 | .fadeOut(duration: 0.5),
151 | .removeFromParentNode()
152 | ])
153 | }
154 |
155 | // Pieces
156 |
157 | // Local
158 |
159 | func performAdamLocalStatic() {
160 | let scn:SCNScene? = SCNScene(named: "art.scnassets/localxAdamfu.scn");
161 |
162 | for child in scn!.rootNode.childNodes {
163 | child.categoryBitMask = 4;
164 |
165 | self.addColorShaderForChild(child: child, red: 1, blue: 1, green: 1);
166 |
167 | child.position = SCNVector3.init(child.position.x, child.position.y+0.1, child.position.z);
168 |
169 | if child.name! == "halo" {
170 | child.categoryBitMask = 3;
171 | child.position = SCNVector3.init(child.position.x, 0.074, child.position.z);
172 | }
173 | else if child.name! == "haloDrip" {
174 | child.categoryBitMask = 3;
175 | }
176 |
177 | self.node!.addChildNode(child);
178 |
179 | }
180 |
181 | DispatchQueue.main.sync {
182 | self.sceneView!.scene.rootNode.addChildNode(self.node!);
183 | }
184 |
185 | if let path = Bundle.main.path(forResource: "GlowInTwoColors", ofType: "plist") {
186 | if let dict = NSDictionary(contentsOfFile: path) {
187 | print("DICT EXISTS");
188 | let dict2 = dict as! [String : AnyObject]
189 | let technique = SCNTechnique(dictionary:dict2)
190 | self.sceneView!.technique = technique
191 | }
192 |
193 | }
194 | }
195 |
196 | func performAdamLocalStroke() {
197 |
198 | let scn:SCNScene? = SCNScene(named: "art.scnassets/localxAdamfu.scn");
199 |
200 | for child in scn!.rootNode.childNodes {
201 | child.categoryBitMask = 4;
202 | child.position = SCNVector3.init(child.position.x, child.position.y+0.1, child.position.z);
203 |
204 | let globalLoopTime:Float = 15;
205 |
206 | if child.name! == "local" {
207 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 0, endTime: 8);
208 | }
209 | else if child.name! == "drip1" {
210 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 0.25, endTime: 0.5);
211 | }
212 | else if child.name! == "drip2" {
213 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 1.75, endTime: 2.5);
214 | }
215 | else if child.name! == "drip3" {
216 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 2.75, endTime: 2.85);
217 | }
218 | else if child.name! == "drip4" {
219 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 3.15, endTime: 3.75);
220 | }
221 | else if child.name! == "drip5" {
222 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 4.1, endTime: 5.4);
223 | }
224 | else if child.name! == "drip6" {
225 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 7, endTime: 7.5);
226 | }
227 | else if child.name! == "drip7" {
228 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 7.05, endTime: 7.55);
229 | }
230 | else if child.name! == "drip8" {
231 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 8, endTime: 8.5);
232 | }
233 | else if child.name! == "halo" {
234 | child.categoryBitMask = 3;
235 | child.position = SCNVector3.init(child.position.x, 0.074, child.position.z);
236 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 8, endTime: 9);
237 | }
238 | else if child.name! == "haloDrip" {
239 | child.categoryBitMask = 3;
240 | self.addStrokeShaderWithTimeForChild(child: child, loopTime: globalLoopTime, startTime: 9, endTime: 9.5);
241 | }
242 |
243 |
244 | self.node!.addChildNode(child);
245 |
246 | }
247 |
248 | DispatchQueue.main.sync {
249 | self.sceneView!.scene.rootNode.addChildNode(self.node!);
250 | }
251 |
252 | if let path = Bundle.main.path(forResource: "GlowInTwoColors", ofType: "plist") {
253 | if let dict = NSDictionary(contentsOfFile: path) {
254 | print("DICT EXISTS");
255 | let dict2 = dict as! [String : AnyObject]
256 | let technique = SCNTechnique(dictionary:dict2)
257 | self.sceneView!.technique = technique
258 | }
259 |
260 | }
261 |
262 | }
263 |
264 | // Loader
265 |
266 | func performLoaderStroke() {
267 | DispatchQueue.main.async {
268 |
269 | let scnName:String = "art.scnassets/logo.scn";
270 |
271 | let scn:SCNScene? = SCNScene(named: scnName); //cylinder
272 | print("update node");
273 |
274 | for child in scn!.rootNode.childNodes {
275 |
276 | child.categoryBitMask = 1;
277 |
278 | print("Child : ", child.name);
279 | let scaleFactor:Float = 1;
280 | child.scale = SCNVector3.init(scaleFactor*child.scale.x,scaleFactor*child.scale.y, scaleFactor*child.scale.z);
281 | child.position = SCNVector3.init(child.position.x*scaleFactor, 0.1, child.position.z*scaleFactor);
282 |
283 | // self.addColorShaderForChild(child: child, red: 1, blue: 1, green: 1);
284 | self.addBackwardsTimedStrokeShaderWithTimeForChild(child: child, loopTime: 10, startTime: 0, endTime: 5);
285 | self.node!.addChildNode(child);
286 | }
287 |
288 | self.sceneView!.scene.rootNode.addChildNode(self.node!);
289 |
290 | if let path = Bundle.main.path(forResource: "Glow", ofType: "plist") {
291 | if let dict = NSDictionary(contentsOfFile: path) {
292 | print("DICT EXISTS");
293 | let dict2 = dict as! [String : AnyObject]
294 | let technique = SCNTechnique(dictionary:dict2)
295 | self.sceneView!.technique = technique
296 | }
297 | }
298 |
299 |
300 | self.offset = 1.5;
301 | self.weight = 0.175;
302 |
303 | self.sceneView!.technique?.setObject(NSNumber(value: 0.6352941176), forKeyedSubscript: "redSymbol" as NSCopying);
304 | self.sceneView!.technique?.setObject(NSNumber(value: 0.1254901961), forKeyedSubscript: "greenSymbol" as NSCopying);
305 | self.sceneView!.technique?.setObject(NSNumber(value: 0.4), forKeyedSubscript: "blueSymbol" as NSCopying);
306 | self.sceneView!.technique?.setObject(NSNumber(value: self.offset), forKeyedSubscript: "offsetSymbol" as NSCopying);
307 | self.sceneView!.technique?.setObject(NSNumber(value: self.weight), forKeyedSubscript: "weightSymbol" as NSCopying);
308 |
309 | self.sceneView!.technique?.setObject(NSNumber(value: 1), forKeyedSubscript: "distanceSymbol" as NSCopying);
310 |
311 | }
312 | }
313 |
314 |
315 |
316 | }
317 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Fade/FadeIn.metal:
--------------------------------------------------------------------------------
1 | //
2 | // Glow.swift
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/12/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 | //static float rand(float2 uv)
42 | //{
43 | // return fract(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
44 | //}
45 | //
46 | //static float2 uv2tri(float2 uv)
47 | //{
48 | // float sx = uv.x - uv.y / 2;
49 | // float sxf = fract(sx);
50 | // float offs = step(fract(1 - uv.y), sxf);
51 | // return float2(floor(sx) * 2 + sxf + offs, uv.y);
52 | //}
53 |
54 | constant float milestoneTimeBreadth = 5;
55 |
56 |
57 | struct Vertex
58 | {
59 | float4 position [[position]];
60 | float2 uv;
61 | half4 color;
62 | float2 texCoords [[user(tex_coords)]];
63 | float time;
64 | };
65 |
66 | vertex Vertex fadeInVertexShader(VertexInput in [[ stage_in ]],
67 | uint vertexID [[vertex_id]],
68 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
69 | constant NodeBuffer& scn_node [[buffer(1)]])
70 | {
71 | Vertex vert;
72 | float alpha = 0.1;
73 | vert.color = half4( half3(1,1,1), alpha);
74 | vert.uv = in.texCoords0;
75 | vert.time = scn_frame.time;
76 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
77 | return vert;
78 | }
79 |
80 |
81 |
82 | fragment half4 fadeInSurfaceFragment(Vertex in [[stage_in]],
83 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
84 | constant NodeBuffer& scn_node [[buffer(1)]],
85 | texture2d texture [[texture(0)]],
86 | sampler texSampler [[sampler(0)]])
87 | {
88 | float timerMilestone = floor(in.time/milestoneTimeBreadth);
89 | float currentTime = in.time;
90 | float timer = (currentTime - timerMilestone*milestoneTimeBreadth);
91 |
92 |
93 | half4 fragColor;
94 | fragColor.rgb = half3(in.color.rgb);
95 | fragColor.a = in.color.a;
96 | fragColor.rgb *= fragColor.a*timer;
97 | return fragColor;
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Fade/FadeInTexture.metal:
--------------------------------------------------------------------------------
1 | //
2 | // FadeInTexture.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/12/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 | //static float rand(float2 uv)
42 | //{
43 | // return fract(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
44 | //}
45 | //
46 | //static float2 uv2tri(float2 uv)
47 | //{
48 | // float sx = uv.x - uv.y / 2;
49 | // float sxf = fract(sx);
50 | // float offs = step(fract(1 - uv.y), sxf);
51 | // return float2(floor(sx) * 2 + sxf + offs, uv.y);
52 | //}
53 |
54 | constant float milestoneTimeBreadth = 5;
55 |
56 |
57 | struct Vertex
58 | {
59 | float4 position [[position]];
60 | float2 uv;
61 | half4 color;
62 | // float2 texCoords [[user(tex_coords)]];
63 | float2 texCoords;
64 | float time;
65 | };
66 |
67 | vertex Vertex fadeInTextureVertexShader(VertexInput in [[ stage_in ]],
68 | uint vertexID [[vertex_id]],
69 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
70 | constant NodeBuffer& scn_node [[buffer(1)]])
71 | {
72 | Vertex vert;
73 |
74 | // float alpha = 0.2;
75 | //
76 | // vert.color = half4( half3(1,1,1), alpha);
77 | vert.texCoords = in.texCoords0[vertexID];
78 | vert.uv = in.texCoords0;
79 | vert.time = scn_frame.time;
80 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
81 | return vert;
82 | }
83 |
84 |
85 |
86 | fragment half4 fadeInTextureSurfaceFragment(Vertex in [[stage_in]],
87 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
88 | constant NodeBuffer& scn_node [[buffer(1)]],
89 | texture2d diffuseTexture [[texture(0)]])
90 | {
91 |
92 | constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
93 | float4 color = diffuseTexture.sample(sampler2d, in.texCoords);
94 |
95 | float timerMilestone = floor(in.time/milestoneTimeBreadth);
96 | float currentTime = in.time;
97 | float timer = (currentTime - timerMilestone*milestoneTimeBreadth);
98 |
99 |
100 | half4 fragColor;
101 | fragColor.rgb = half3(color.rgb);
102 | fragColor.a = 0.2*timer;
103 | // fragColor.a = 1*timer;//in.color.a
104 | fragColor.rgb *= fragColor.a;
105 | return fragColor;
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Standard/Color.metal:
--------------------------------------------------------------------------------
1 | //
2 | // Color.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 9/5/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 | struct TimeVariables {
42 | float loopTime;
43 | float startTime;
44 | float endTime;
45 | float red;
46 | float blue;
47 | float green;
48 | };
49 |
50 |
51 | struct Vertex
52 | {
53 | float4 position [[position]];
54 | float2 uv;
55 | half4 color;
56 | float2 texCoords [[user(tex_coords)]];
57 | float time;
58 | };
59 |
60 | vertex Vertex ColorVertexShader(VertexInput in [[ stage_in ]],
61 | uint vertexID [[vertex_id]],
62 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
63 | constant NodeBuffer& scn_node [[buffer(1)]],
64 | constant TimeVariables& timeVariables [[buffer(2)]])
65 | {
66 | Vertex vert;
67 | vert.color = half4( half3(timeVariables.red, timeVariables.blue, timeVariables.green), 1);
68 | vert.uv = in.texCoords0;
69 | vert.time = scn_frame.time;
70 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
71 | return vert;
72 | }
73 |
74 |
75 |
76 | fragment half4 ColorSurfaceFragment(Vertex in [[stage_in]],
77 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
78 | constant NodeBuffer& scn_node [[buffer(1)]],
79 | texture2d texture [[texture(0)]],
80 | sampler texSampler [[sampler(0)]],
81 | constant TimeVariables& timeVariables [[buffer(2)]])
82 | {
83 | half4 fragColor;
84 | fragColor.rgb = half3(in.color.rgb);
85 | fragColor.a = in.color.a;
86 | fragColor *= in.color.a;
87 | return fragColor;
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Standard/Texture.metal:
--------------------------------------------------------------------------------
1 | //
2 | // Texture.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/12/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 |
42 |
43 | struct Vertex
44 | {
45 | float4 position [[position]];
46 | float2 uv;
47 | half4 color;
48 | float2 texCoords;
49 | float time;
50 | };
51 |
52 | vertex Vertex TextureVertexShader(VertexInput in [[ stage_in ]],
53 | uint vertexID [[vertex_id]],
54 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
55 | constant NodeBuffer& scn_node [[buffer(1)]])
56 | {
57 | Vertex vert;
58 | vert.texCoords = in.texCoords0;
59 | vert.time = scn_frame.time;
60 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
61 | return vert;
62 | }
63 |
64 |
65 |
66 | fragment half4 TextureSurfaceFragment(Vertex in [[stage_in]],
67 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
68 | constant NodeBuffer& scn_node [[buffer(1)]],
69 | texture2d diffuseTexture [[texture(1)]])
70 | {
71 |
72 | constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
73 | float4 color = diffuseTexture.sample(sampler2d, in.texCoords);
74 | return half4(color);
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Stroke/BackwardStroke.metal:
--------------------------------------------------------------------------------
1 | //
2 | // BackwardStroke.swift
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/12/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 | //static float rand(float2 uv)
42 | //{
43 | // return fract(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
44 | //}
45 | //
46 | //static float2 uv2tri(float2 uv)
47 | //{
48 | // float sx = uv.x - uv.y / 2;
49 | // float sxf = fract(sx);
50 | // float offs = step(fract(1 - uv.y), sxf);
51 | // return float2(floor(sx) * 2 + sxf + offs, uv.y);
52 | //}
53 |
54 | constant float milestoneTimeBreadth = 5;
55 |
56 |
57 | struct Vertex
58 | {
59 | float4 position [[position]];
60 | float2 uv;
61 | half4 color;
62 | float2 texCoords [[user(tex_coords)]];
63 | float time;
64 | };
65 |
66 | vertex Vertex backwardStrokeVertexShader(VertexInput in [[ stage_in ]],
67 | uint vertexID [[vertex_id]],
68 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
69 | constant NodeBuffer& scn_node [[buffer(1)]])
70 | {
71 | Vertex vert;
72 | float alpha = 1;
73 | vert.color = half4( half3(1,1,1), alpha);
74 | vert.uv = in.texCoords0;
75 | vert.time = scn_frame.time;
76 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
77 | return vert;
78 | }
79 |
80 |
81 |
82 | fragment half4 backwardStrokeSurfaceFragment(Vertex in [[stage_in]],
83 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
84 | constant NodeBuffer& scn_node [[buffer(1)]],
85 | texture2d texture [[texture(0)]],
86 | sampler texSampler [[sampler(0)]])
87 | {
88 | float timerMilestone = floor(in.time/milestoneTimeBreadth);
89 | float currentTime = in.time;
90 | float timer = (currentTime - timerMilestone*milestoneTimeBreadth);
91 |
92 | float2 vUv = in.uv;
93 |
94 | if (in.uv.y > timer/milestoneTimeBreadth) {
95 | discard_fragment();
96 | }
97 |
98 | half4 fragColor;
99 | fragColor.rgb = half3(in.color.rgb);
100 | fragColor.a = in.color.a;
101 | // fragColor.rgb *= fragColor.a;
102 | return fragColor;
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Stroke/BackwardsTimedStroke.metal:
--------------------------------------------------------------------------------
1 | //
2 | // BackwardsTimedStroke.metal
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/6/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 |
10 | #include
11 | using namespace metal;
12 | #include
13 |
14 |
15 | struct NodeBuffer {
16 | float4x4 modelTransform;
17 | float4x4 modelViewTransform;
18 | float4x4 normalTransform;
19 | float4x4 modelViewProjectionTransform;
20 | float2x3 boundingBox;
21 |
22 | float4x4 viewTransform;
23 | float4x4 inverseViewTransform; // view space to world space
24 | float4x4 projectionTransform;
25 | float4x4 viewProjectionTransform;
26 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
27 | float4 ambientLightingColor;
28 | float4 fogColor;
29 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
30 | float time; // system time elapsed since first render with this shader
31 | float sinTime; // precalculated sin(time)
32 | float cosTime; // precalculated cos(time)
33 | float random01; // random value between 0.0 and 1.0
34 | };
35 |
36 | typedef struct {
37 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
38 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
39 | half4 color [[ attribute(SCNVertexSemanticColor)]];
40 |
41 | } VertexInput;
42 |
43 |
44 | //constant float loopTime = 10; // In Seconds
45 | //constant float startTime = 1.25;
46 | //constant float endTime = 9.25;
47 |
48 | struct TimeVariables {
49 | float loopTime;
50 | float startTime;
51 | float endTime;
52 | };
53 |
54 | struct DisplayVariables {
55 | float show;
56 | };
57 |
58 | struct Vertex
59 | {
60 | float4 position [[position]];
61 | float2 uv;
62 | half4 color;
63 | float2 texCoords [[user(tex_coords)]];
64 | float time;
65 | float4 modelViewProjectionTransformColumn;
66 | };
67 |
68 | vertex Vertex BackwardsTimedStrokeVertexShader(VertexInput in [[ stage_in ]],
69 | uint vertexID [[vertex_id]],
70 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
71 | constant NodeBuffer& scn_node [[buffer(1)]])
72 | {
73 | Vertex vert;
74 | vert.color = half4( half3(1,1,1), 0.1);
75 | vert.uv = in.texCoords0;
76 | vert.time = scn_frame.time;
77 | vert.modelViewProjectionTransformColumn = scn_node.modelViewProjectionTransform[3];
78 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
79 | return vert;
80 | }
81 |
82 |
83 |
84 | fragment half4 BackwardsTimedStrokeSurfaceFragment(Vertex in [[stage_in]],
85 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
86 | constant NodeBuffer& scn_node [[buffer(1)]],
87 | constant TimeVariables& timeVariables [[buffer(2)]],
88 | constant DisplayVariables& displayVariables [[buffer(3)]])
89 | {
90 |
91 | // float currentTime = in.time;
92 | // float timerMilestone = floor(currentTime/timeVariables.loopTime);
93 | //
94 | // float loopTimer = (currentTime - timerMilestone*timeVariables.loopTime);
95 | //
96 | // if ( loopTimer < timeVariables.startTime) {
97 | // // hasnt started
98 | // discard_fragment();
99 | // }
100 | // else if (loopTimer < timeVariables.endTime) {
101 | // // has started
102 | //
103 | // float showUVsIfSmallerThan = (loopTimer-timeVariables.startTime)/(timeVariables.endTime-timeVariables.startTime);
104 | //
105 | // if ((in.uv.y) > showUVsIfSmallerThan) {
106 | // // These Are Invalid, remove
107 | // discard_fragment();
108 | // }
109 | //
110 | // }
111 | // else {
112 | // // SHOW ALL
113 | // }
114 |
115 | if ((in.uv.y) > displayVariables.show) {
116 | // These Are Invalid, remove
117 | discard_fragment();
118 | }
119 | else {
120 | // show
121 | }
122 |
123 |
124 |
125 | half4 fragColor;
126 | fragColor.rgb = half3(in.color.rgb);
127 | fragColor.a = in.color.a;
128 | // fragColor.rgb *= fragColor.a;
129 | return fragColor;
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Stroke/BackwardsTimedStrokeTexture.metal:
--------------------------------------------------------------------------------
1 | //
2 | // BackwardsTimedStrokeTexture.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 11/19/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 |
42 | struct Vertex
43 | {
44 | float4 position [[position]];
45 | float2 uv;
46 | half4 color;
47 | // float2 texCoords [[user(tex_coords)]];
48 | float2 texCoords;
49 | float time;
50 | };
51 |
52 | struct TimeVariables {
53 | float loopTime;
54 | float startTime;
55 | float endTime;
56 | };
57 |
58 | vertex Vertex BackwardsTimedStrokeTextureVertexShader(VertexInput in [[ stage_in ]],
59 | uint vertexID [[vertex_id]],
60 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
61 | constant NodeBuffer& scn_node [[buffer(1)]])
62 | {
63 | Vertex vert;
64 |
65 | // float alpha = 0.2;
66 | //
67 | // vert.color = half4( half3(1,1,1), alpha);
68 | vert.texCoords = in.texCoords0;
69 | vert.uv = in.texCoords0;
70 | vert.time = scn_frame.time;
71 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
72 | return vert;
73 | }
74 |
75 |
76 |
77 | fragment half4 BackwardsTimedStrokeTextureSurfaceFragment(Vertex in [[stage_in]],
78 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
79 | constant NodeBuffer& scn_node [[buffer(1)]],
80 | texture2d diffuseTexture [[texture(0)]],
81 | constant TimeVariables& timeVariables [[buffer(2)]])
82 | {
83 | constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
84 | float4 color = diffuseTexture.sample(sampler2d, in.texCoords);
85 |
86 | float currentTime = in.time;
87 | float timerMilestone = floor(currentTime/timeVariables.loopTime);
88 |
89 | float loopTimer = (currentTime - timerMilestone*timeVariables.loopTime);
90 |
91 | if ( loopTimer < timeVariables.startTime) {
92 | // hasnt started
93 | discard_fragment();
94 | }
95 | else if (loopTimer < timeVariables.endTime) {
96 | // has started
97 |
98 | float showUVsIfSmallerThan = (loopTimer-timeVariables.startTime)/(timeVariables.endTime-timeVariables.startTime);
99 |
100 | if ((in.uv.y) > showUVsIfSmallerThan) {
101 | // These Are Invalid, remove
102 | discard_fragment();
103 | }
104 |
105 | }
106 | else {
107 | // SHOW ALL
108 | }
109 |
110 | half4 fragColor;
111 | fragColor.rgb = half3(color.rgb);
112 | fragColor.a = color.a;
113 | // fragColor.rgb *= fragColor.a;
114 | return fragColor;
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Stroke/Stroke.metal:
--------------------------------------------------------------------------------
1 | //
2 | // Stroke.swift
3 | // Delasign
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/12/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 | constant float milestoneTimeBreadth = 5;
42 |
43 |
44 | struct Vertex
45 | {
46 | float4 position [[position]];
47 | float2 uv;
48 | half4 color;
49 | float2 texCoords [[user(tex_coords)]];
50 | float time;
51 | };
52 |
53 | vertex Vertex strokeVertexShader(VertexInput in [[ stage_in ]],
54 | uint vertexID [[vertex_id]],
55 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
56 | constant NodeBuffer& scn_node [[buffer(1)]])
57 | {
58 | Vertex vert;
59 | vert.color = half4( half3(1,1,1), 0.1);
60 | vert.uv = in.texCoords0;
61 | vert.time = scn_frame.time;
62 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
63 | return vert;
64 | }
65 |
66 |
67 |
68 | fragment half4 strokeSurfaceFragment(Vertex in [[stage_in]],
69 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
70 | constant NodeBuffer& scn_node [[buffer(1)]],
71 | texture2d texture [[texture(0)]],
72 | sampler texSampler [[sampler(0)]])
73 | {
74 | float timerMilestone = floor(in.time/milestoneTimeBreadth);
75 | float currentTime = in.time;
76 | float timer = (currentTime - timerMilestone*milestoneTimeBreadth);
77 |
78 | float2 vUv = in.uv;
79 |
80 | if ((1-in.uv.y) > timer/milestoneTimeBreadth) {
81 | discard_fragment();
82 | }
83 |
84 | half4 fragColor;
85 | fragColor.rgb = half3(in.color.rgb);
86 | fragColor.a = in.color.a;
87 | return fragColor;
88 | }
89 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Stroke/TimedStroke.metal:
--------------------------------------------------------------------------------
1 | //
2 | // AdamLocalStroke.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 9/21/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 |
10 | #include
11 | using namespace metal;
12 | #include
13 |
14 |
15 | struct NodeBuffer {
16 | float4x4 modelTransform;
17 | float4x4 modelViewTransform;
18 | float4x4 normalTransform;
19 | float4x4 modelViewProjectionTransform;
20 | float2x3 boundingBox;
21 |
22 | float4x4 viewTransform;
23 | float4x4 inverseViewTransform; // view space to world space
24 | float4x4 projectionTransform;
25 | float4x4 viewProjectionTransform;
26 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
27 | float4 ambientLightingColor;
28 | float4 fogColor;
29 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
30 | float time; // system time elapsed since first render with this shader
31 | float sinTime; // precalculated sin(time)
32 | float cosTime; // precalculated cos(time)
33 | float random01; // random value between 0.0 and 1.0
34 | };
35 |
36 | typedef struct {
37 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
38 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
39 | half4 color [[ attribute(SCNVertexSemanticColor)]];
40 |
41 | } VertexInput;
42 |
43 |
44 | //constant float loopTime = 10; // In Seconds
45 | //constant float startTime = 1.25;
46 | //constant float endTime = 9.25;
47 |
48 | struct TimeVariables {
49 | float loopTime;
50 | float startTime;
51 | float endTime;
52 | };
53 |
54 | struct Vertex
55 | {
56 | float4 position [[position]];
57 | float2 uv;
58 | half4 color;
59 | float2 texCoords [[user(tex_coords)]];
60 | float time;
61 | float4 modelViewProjectionTransformColumn;
62 | };
63 |
64 | vertex Vertex TimedStrokeVertexShader(VertexInput in [[ stage_in ]],
65 | uint vertexID [[vertex_id]],
66 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
67 | constant NodeBuffer& scn_node [[buffer(1)]])
68 | {
69 | Vertex vert;
70 | vert.color = half4( half3(1,1,1), 0.1);
71 | vert.uv = in.texCoords0;
72 | vert.time = scn_frame.time;
73 | vert.modelViewProjectionTransformColumn = scn_node.modelViewProjectionTransform[3];
74 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
75 | return vert;
76 | }
77 |
78 |
79 |
80 | fragment half4 TimedStrokeSurfaceFragment(Vertex in [[stage_in]],
81 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
82 | constant NodeBuffer& scn_node [[buffer(1)]],
83 | constant TimeVariables& timeVariables [[buffer(2)]])
84 | {
85 |
86 | float currentTime = in.time;
87 | float timerMilestone = floor(currentTime/timeVariables.loopTime);
88 |
89 | float loopTimer = (currentTime - timerMilestone*timeVariables.loopTime);
90 |
91 | if ( loopTimer < timeVariables.startTime) {
92 | // hasnt started
93 | discard_fragment();
94 | }
95 | else if (loopTimer < timeVariables.endTime) {
96 | // has started
97 |
98 | float showUVsIfSmallerThan = (loopTimer-timeVariables.startTime)/(timeVariables.endTime-timeVariables.startTime);
99 |
100 | if ((1-in.uv.y) > showUVsIfSmallerThan) {
101 | // These Are Invalid, remove
102 | discard_fragment();
103 | }
104 |
105 | }
106 | else {
107 | // SHOW ALL
108 | }
109 |
110 | half4 fragColor;
111 | fragColor.rgb = half3(in.color.rgb);
112 | fragColor.a = in.color.a;
113 | // fragColor.rgb *= fragColor.a;
114 | return fragColor;
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Shaders/Stroke/TimedStrokeTexture.metal:
--------------------------------------------------------------------------------
1 | //
2 | // StrokeTexture.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 8/12/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | #include
10 | using namespace metal;
11 | #include
12 |
13 | struct NodeBuffer {
14 | float4x4 modelTransform;
15 | float4x4 modelViewTransform;
16 | float4x4 normalTransform;
17 | float4x4 modelViewProjectionTransform;
18 | float2x3 boundingBox;
19 |
20 | float4x4 viewTransform;
21 | float4x4 inverseViewTransform; // view space to world space
22 | float4x4 projectionTransform;
23 | float4x4 viewProjectionTransform;
24 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
25 | float4 ambientLightingColor;
26 | float4 fogColor;
27 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
28 | float time; // system time elapsed since first render with this shader
29 | float sinTime; // precalculated sin(time)
30 | float cosTime; // precalculated cos(time)
31 | float random01; // random value between 0.0 and 1.0
32 | };
33 |
34 | typedef struct {
35 | float3 position [[ attribute(SCNVertexSemanticPosition) ]];
36 | float2 texCoords0 [[ attribute(SCNVertexSemanticTexcoord0) ]];
37 | half4 color [[ attribute(SCNVertexSemanticColor)]];
38 |
39 | } VertexInput;
40 |
41 |
42 | struct Vertex
43 | {
44 | float4 position [[position]];
45 | float2 uv;
46 | half4 color;
47 | // float2 texCoords [[user(tex_coords)]];
48 | float2 texCoords;
49 | float time;
50 | };
51 |
52 | struct TimeVariables {
53 | float loopTime;
54 | float startTime;
55 | float endTime;
56 | };
57 |
58 | vertex Vertex TimedStrokeTextureVertexShader(VertexInput in [[ stage_in ]],
59 | uint vertexID [[vertex_id]],
60 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
61 | constant NodeBuffer& scn_node [[buffer(1)]])
62 | {
63 | Vertex vert;
64 |
65 | // float alpha = 0.2;
66 | //
67 | // vert.color = half4( half3(1,1,1), alpha);
68 | vert.texCoords = in.texCoords0;
69 | vert.uv = in.texCoords0;
70 | vert.time = scn_frame.time;
71 | vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);
72 | return vert;
73 | }
74 |
75 |
76 |
77 | fragment half4 TimedStrokeTextureSurfaceFragment(Vertex in [[stage_in]],
78 | constant SCNSceneBuffer& scn_frame [[buffer(0)]],
79 | constant NodeBuffer& scn_node [[buffer(1)]],
80 | texture2d diffuseTexture [[texture(0)]],
81 | constant TimeVariables& timeVariables [[buffer(2)]])
82 | {
83 |
84 | float currentTime = in.time;
85 | float timerMilestone = floor(currentTime/timeVariables.loopTime);
86 |
87 | float loopTimer = (currentTime - timerMilestone*timeVariables.loopTime);
88 |
89 | if ( loopTimer < timeVariables.startTime) {
90 | // hasnt started
91 | discard_fragment();
92 | }
93 | else if (loopTimer < timeVariables.endTime) {
94 | // has started
95 |
96 | float showUVsIfSmallerThan = (loopTimer-timeVariables.startTime)/(timeVariables.endTime-timeVariables.startTime);
97 |
98 | if ((1-in.uv.y) > showUVsIfSmallerThan) {
99 | // These Are Invalid, remove
100 | discard_fragment();
101 | }
102 |
103 | }
104 | else {
105 | // SHOW ALL
106 | }
107 |
108 | half4 fragColor;
109 | fragColor.rgb = half3(in.color.rgb);
110 | fragColor.a = in.color.a;
111 | // fragColor.rgb *= fragColor.a;
112 | return fragColor;
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/SpecialEffects/Glow/Glow.metal:
--------------------------------------------------------------------------------
1 | //
2 | // TextureGlow.metal
3 | // Artzy
4 | //
5 | // Created by Oscar De la Hera Gomez on 11/20/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 | #include
9 |
10 | using namespace metal;
11 | #include
12 | #include
13 |
14 |
15 | struct NodeBuffer {
16 | float4x4 modelTransform;
17 | float4x4 modelViewTransform;
18 | float4x4 normalTransform;
19 | float4x4 modelViewProjectionTransform;
20 | float2x3 boundingBox;
21 |
22 | float4x4 viewTransform;
23 | float4x4 inverseViewTransform; // view space to world space
24 | float4x4 projectionTransform;
25 | float4x4 viewProjectionTransform;
26 | float4x4 viewToCubeTransform; // view space to cube texture space (right-handed, y-axis-up)
27 | float4 ambientLightingColor;
28 | float4 fogColor;
29 | float3 fogParameters; // x: -1/(end-start) y: 1-start*x z: exponent
30 | float time; // system time elapsed since first render with this shader
31 | float sinTime; // precalculated sin(time)
32 | float cosTime; // precalculated cos(time)
33 | float random01; // random value between 0.0 and 1.0
34 | };
35 |
36 | struct modelViewProjectionTransform
37 | {
38 | float4x4 transform;
39 | };
40 |
41 | struct custom_vertex_t
42 | {
43 | float4 position [[attribute(SCNVertexSemanticPosition)]];
44 | float4 normal [[attribute(SCNVertexSemanticNormal)]];
45 | half4 color [[attribute(SCNVertexSemanticColor)]];
46 | float3 boneWeights [[attribute(SCNVertexSemanticBoneWeights)]];
47 | };
48 |
49 | struct out_vertex_t
50 | {
51 | float4 position [[position]];
52 | float2 uv;
53 | };
54 |
55 | typedef struct {
56 | float red;
57 | float blue;
58 | float green;
59 | float offset;
60 | float weight;
61 | float distanceToCamera;
62 | } Uniforms;
63 |
64 |
65 | vertex out_vertex_t texture_mask_vertex(custom_vertex_t in [[stage_in]])
66 | {
67 | out_vertex_t out;
68 | out.position = in.position;
69 | return out;
70 | };
71 |
72 |
73 | fragment half4 texture_mask_fragment(out_vertex_t in [[stage_in]],
74 | texture2d colorSampler [[texture(0)]])
75 | {
76 | constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
77 | return half4(1.0);
78 | };
79 |
80 |
81 | ////////////
82 |
83 | constexpr sampler s = sampler(coord::normalized,
84 | r_address::clamp_to_edge,
85 | t_address::repeat,
86 | filter::linear);
87 |
88 | vertex out_vertex_t texture_combine_vertex(custom_vertex_t in [[stage_in]])
89 | {
90 | out_vertex_t out;
91 | out.position = in.position;
92 | out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
93 | return out;
94 | };
95 |
96 |
97 | fragment half4 texture_combine_fragment(out_vertex_t vert [[stage_in]],
98 | texture2d colorSampler [[texture(0)]],
99 | texture2d maskSampler [[texture(1)]],
100 | constant Uniforms& uniforms [[ buffer(0) ]])
101 | {
102 |
103 | float4 FragmentColor = colorSampler.sample( s, vert.uv);
104 | float4 maskColor = maskSampler.sample(s, vert.uv);
105 | // Don't render glow on top of the object itself
106 | if ( maskColor.g > 0.5 ) {
107 | return half4(FragmentColor);
108 | }
109 |
110 |
111 |
112 | float3 glowColor = float3(uniforms.red, uniforms.green, uniforms.blue);
113 |
114 | float alpha = maskColor.r;
115 | float3 out = FragmentColor.rgb * ( 1.0 - alpha ) + alpha * glowColor;
116 | return half4( float4(out.rgb, 1.0) );
117 | }
118 |
119 | ///// Blur //////
120 |
121 | vertex out_vertex_t texture_blur_vertex(custom_vertex_t in [[stage_in]])
122 | {
123 | out_vertex_t out;
124 | out.position = in.position;
125 | out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
126 | return out;
127 | };
128 |
129 | // http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
130 | //constant float weightConstant = 0.175;//0.175
131 | constant float offset[] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
132 | //constant float weight[] = { weightConstant, weightConstant, weightConstant, weightConstant, weightConstant }; //{ 0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162 };
133 | constant float bufferSize = 512.0;
134 |
135 | fragment half4 texture_blur_fragment_h(out_vertex_t vert [[stage_in]],
136 | texture2d maskSampler [[texture(0)]],
137 | constant Uniforms& uniforms [[ buffer(0) ]])
138 | {
139 | // float4 modelViewProjectionTransform = vert.modelViewProjectionTransformColumn;
140 |
141 | float4 FragmentColor = maskSampler.sample( s, vert.uv);
142 | float FragmentR = FragmentColor.r * uniforms.weight;
143 |
144 |
145 | for (int i=1; i<5; i++) {
146 | FragmentR += maskSampler.sample( s, ( vert.uv + float2(offset[i] * uniforms.offset, 0.0)/bufferSize / uniforms.distanceToCamera ) ).r * uniforms.weight;
147 | FragmentR += maskSampler.sample( s, ( vert.uv - float2(offset[i] * uniforms.offset, 0.0)/bufferSize / uniforms.distanceToCamera ) ).r * uniforms.weight;
148 | }
149 | return half4(FragmentR, FragmentColor.g, FragmentColor.b, 1.0);
150 | }
151 |
152 | fragment half4 texture_blur_fragment_v(out_vertex_t vert [[stage_in]],
153 | texture2d maskSampler [[texture(0)]],
154 | constant Uniforms& uniforms [[ buffer(0) ]])
155 | {
156 |
157 | // float4 modelViewProjectionTransform = vert.modelViewProjectionTransformColumn;
158 |
159 | float4 FragmentColor = maskSampler.sample( s, vert.uv);
160 | float FragmentR = FragmentColor.r * uniforms.weight;
161 |
162 | for (int i=1; i<5; i++) {
163 | FragmentR += maskSampler.sample( s, ( vert.uv + float2(0.0, offset[i] * uniforms.offset)/bufferSize / uniforms.distanceToCamera ) ).r * uniforms.weight;
164 | FragmentR += maskSampler.sample( s, ( vert.uv - float2(0.0, offset[i] * uniforms.offset)/bufferSize / uniforms.distanceToCamera ) ).r * uniforms.weight;
165 | }
166 |
167 | return half4(FragmentR, FragmentColor.g, FragmentColor.b, 1.0);
168 |
169 | };
170 |
171 |
172 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/SpecialEffects/Glow/Glow.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | passes
6 |
7 | pass_blur_h
8 |
9 | colorStates
10 |
11 | clear
12 |
13 |
14 | inputs
15 |
16 | red
17 | redSymbol
18 | blue
19 | blueSymbol
20 | green
21 | greenSymbol
22 | offset
23 | offsetSymbol
24 | weight
25 | weightSymbol
26 | distanceToCamera
27 | distanceSymbol
28 | maskSampler
29 | MASK
30 |
31 | outputs
32 |
33 | color
34 | MASK
35 |
36 | metalFragmentShader
37 | texture_blur_fragment_h
38 | program
39 | doesntexist
40 | draw
41 | DRAW_QUAD
42 | metalVertexShader
43 | texture_blur_vertex
44 |
45 | pass_draw_masks
46 |
47 | inputs
48 |
49 | red
50 | redSymbol
51 | blue
52 | blueSymbol
53 | green
54 | greenSymbol
55 | offset
56 | offsetSymbol
57 | weight
58 | weightSymbol
59 | distanceToCamera
60 | distanceSymbol
61 |
62 | outputs
63 |
64 | color
65 | MASK
66 |
67 | metalFragmentShader
68 | texture_mask_vertex
69 | draw
70 | DRAW_SCENE
71 | metalVertexShader
72 | texture_mask_fragment
73 |
74 | pass_blur_v
75 |
76 | colorStates
77 |
78 | clear
79 |
80 |
81 | inputs
82 |
83 | red
84 | redSymbol
85 | blue
86 | blueSymbol
87 | green
88 | greenSymbol
89 | offset
90 | offsetSymbol
91 | weight
92 | weightSymbol
93 | distanceToCamera
94 | distanceSymbol
95 | maskSampler
96 | MASK
97 |
98 | outputs
99 |
100 | color
101 | MASK
102 |
103 | metalFragmentShader
104 | texture_blur_fragment_v
105 | program
106 | doesntexist
107 | draw
108 | DRAW_QUAD
109 | metalVertexShader
110 | texture_blur_vertex
111 |
112 | pass_combine
113 |
114 | colorStates
115 |
116 | clear
117 |
118 |
119 | inputs
120 |
121 | red
122 | redSymbol
123 | blue
124 | blueSymbol
125 | green
126 | greenSymbol
127 | offset
128 | offsetSymbol
129 | weight
130 | weightSymbol
131 | distanceToCamera
132 | distanceSymbol
133 | colorSampler
134 | COLOR
135 | maskSampler
136 | MASK
137 |
138 | outputs
139 |
140 | color
141 | COLOR
142 |
143 | metalFragmentShader
144 | texture_combine_fragment
145 | program
146 | doesntexist
147 | draw
148 | DRAW_QUAD
149 | metalVertexShader
150 | texture_combine_vertex
151 |
152 |
153 | sequence
154 |
155 | pass_draw_masks
156 | pass_blur_h
157 | pass_blur_v
158 | pass_blur_h
159 | pass_blur_v
160 | pass_combine
161 |
162 | symbols
163 |
164 | redSymbol
165 |
166 | type
167 | float
168 |
169 | blueSymbol
170 |
171 | type
172 | float
173 |
174 | greenSymbol
175 |
176 | type
177 | float
178 |
179 | offsetSymbol
180 |
181 | type
182 | float
183 |
184 | weightSymbol
185 |
186 | type
187 | float
188 |
189 | distanceSymbol
190 |
191 | type
192 | float
193 |
194 |
195 | targets
196 |
197 | MASK
198 |
199 | format
200 | rgb
201 | size
202 | 512x512
203 | scaleFactor
204 | 1
205 | type
206 | color
207 |
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/SpecialEffects/GlowInTwoColors/GlowBlue.metal:
--------------------------------------------------------------------------------
1 | //
2 | // GlowBlue.metal
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/24/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 | #include
9 |
10 | using namespace metal;
11 | #include
12 | #include
13 |
14 |
15 |
16 |
17 |
18 | struct custom_node_t3 {
19 | float4x4 modelTransform;
20 | float4x4 inverseModelTransform;
21 | float4x4 modelViewTransform;
22 | float4x4 inverseModelViewTransform;
23 | float4x4 normalTransform; // Inverse transpose of modelViewTransform
24 | float4x4 modelViewProjectionTransform;
25 | float4x4 inverseModelViewProjectionTransform;
26 | float2x3 boundingBox;
27 | float2x3 worldBoundingBox;
28 | };
29 |
30 | struct custom_vertex_t
31 | {
32 | float4 position [[attribute(SCNVertexSemanticPosition)]];
33 | float4 normal [[attribute(SCNVertexSemanticNormal)]];
34 | half4 color [[attribute(SCNVertexSemanticColor)]];
35 | float3 boneWeights [[attribute(SCNVertexSemanticBoneWeights)]];
36 | };
37 |
38 | struct out_vertex_t
39 | {
40 | float4 position [[position]];
41 | float2 uv;
42 | };
43 |
44 | typedef struct {
45 | float symbolAsCalledInMetal;
46 | } Uniforms;
47 |
48 |
49 | vertex out_vertex_t blue_mask_vertex(custom_vertex_t in [[stage_in]],
50 | constant Uniforms& uniforms [[ buffer(0) ]])
51 | {
52 | out_vertex_t out;
53 | out.position = in.position;
54 | return out;
55 | };
56 |
57 |
58 | fragment half4 blue_mask_fragment(out_vertex_t in [[stage_in]],
59 | texture2d colorSampler [[texture(0)]],
60 | constant Uniforms& uniforms [[ buffer(0) ]])
61 | {
62 | constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
63 | return half4(1.0);
64 | };
65 |
66 |
67 | ////////////
68 |
69 | constexpr sampler s = sampler(coord::normalized,
70 | r_address::clamp_to_edge,
71 | t_address::repeat,
72 | filter::linear);
73 |
74 | struct MyNodeBuffer {
75 | float4x4 modelTransform;
76 | float4x4 modelViewTransform;
77 | float4x4 normalTransform;
78 | float4x4 modelViewProjectionTransform;
79 | };
80 |
81 |
82 | vertex out_vertex_t blue_combine_vertex(custom_vertex_t in [[stage_in]],
83 | constant Uniforms& uniforms [[ buffer(0) ]])
84 | {
85 | float test = uniforms.symbolAsCalledInMetal;
86 | out_vertex_t out;
87 | out.position = in.position;
88 | out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
89 | return out;
90 | };
91 |
92 |
93 | fragment half4 blue_combine_fragment(out_vertex_t vert [[stage_in]],
94 | texture2d colorSampler [[texture(0)]],
95 | texture2d maskSampler [[texture(1)]],
96 | constant Uniforms& uniforms [[ buffer(0) ]])
97 | {
98 | float test = uniforms.symbolAsCalledInMetal;
99 | float4 FragmentColor = colorSampler.sample( s, vert.uv);
100 | float4 maskColor = maskSampler.sample(s, vert.uv);
101 |
102 | // Don't render glow on top of the object itself
103 | if ( maskColor.g > 0.5 ) {
104 | return half4(FragmentColor);
105 | }
106 |
107 | float r = 0.1411764706; // 0.56
108 | float g = 0.4; // 0.84
109 | float b = 0.6470588235; // 0.95
110 |
111 | float3 glowColor = float3(r, g, b);
112 |
113 | float alpha = maskColor.r;
114 | float3 out = FragmentColor.rgb * ( 1.0 - alpha ) + alpha * glowColor;
115 | return half4( float4(out.rgb, 1.0) );
116 | }
117 |
118 | ///// Blur //////
119 |
120 | vertex out_vertex_t blue_blur_vertex(custom_vertex_t in [[stage_in]],
121 | constant Uniforms& uniforms [[ buffer(0) ]])
122 | {
123 | float test = uniforms.symbolAsCalledInMetal;
124 | out_vertex_t out;
125 | out.position = in.position;
126 | out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
127 | return out;
128 | };
129 |
130 | // http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
131 | constant float weightConstant = 0.175;
132 | constant float offset[] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
133 | constant float weight[] = { weightConstant, weightConstant, weightConstant, weightConstant, weightConstant }; //{ 0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162 };
134 | constant float bufferSize = 512.0;
135 |
136 | fragment half4 blue_blur_fragment_h(out_vertex_t vert [[stage_in]],
137 | texture2d maskSampler [[texture(0)]],
138 | constant Uniforms& uniforms [[ buffer(0) ]])
139 | {
140 | float test = uniforms.symbolAsCalledInMetal;
141 | float4 FragmentColor = maskSampler.sample( s, vert.uv);
142 | float FragmentR = FragmentColor.r * weight[0];
143 |
144 |
145 | for (int i=1; i<5; i++) {
146 | FragmentR += maskSampler.sample( s, ( vert.uv + float2(offset[i], 0.0)/bufferSize ) ).r * weight[i];
147 | FragmentR += maskSampler.sample( s, ( vert.uv - float2(offset[i], 0.0)/bufferSize ) ).r * weight[i];
148 | }
149 | return half4(FragmentR, FragmentColor.g, FragmentColor.b, 1.0);
150 | }
151 |
152 | fragment half4 blue_blur_fragment_v(out_vertex_t vert [[stage_in]],
153 | texture2d maskSampler [[texture(0)]],
154 | constant Uniforms& uniforms [[ buffer(0) ]])
155 | {
156 | float test = uniforms.symbolAsCalledInMetal;
157 | float4 FragmentColor = maskSampler.sample( s, vert.uv);
158 | float FragmentR = FragmentColor.r * weight[0];
159 |
160 | for (int i=1; i<5; i++) {
161 | FragmentR += maskSampler.sample( s, ( vert.uv + float2(0.0, offset[i])/bufferSize ) ).r * weight[i];
162 | FragmentR += maskSampler.sample( s, ( vert.uv - float2(0.0, offset[i])/bufferSize ) ).r * weight[i];
163 | }
164 |
165 | return half4(FragmentR, FragmentColor.g, FragmentColor.b, 1.0);
166 |
167 | };
168 |
169 |
170 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/SpecialEffects/GlowInTwoColors/GlowInTwoColors.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | passes
6 |
7 | pass_red_blur_v
8 |
9 | colorStates
10 |
11 | clear
12 |
13 |
14 | inputs
15 |
16 | symbolAsCalledInMetal
17 | customVariableSymbol
18 | maskSampler
19 | MASK
20 |
21 | outputs
22 |
23 | color
24 | MASK
25 |
26 | metalFragmentShader
27 | red_blur_fragment_v
28 | program
29 | doesntexist
30 | draw
31 | DRAW_QUAD
32 | metalVertexShader
33 | red_blur_vertex
34 |
35 | pass_red_combine
36 |
37 | colorStates
38 |
39 | clear
40 |
41 |
42 | inputs
43 |
44 | symbolAsCalledInMetal
45 | customVariableSymbol
46 | colorSampler
47 | COLOR
48 | maskSampler
49 | MASK
50 |
51 | outputs
52 |
53 | color
54 | COLOR
55 |
56 | metalFragmentShader
57 | red_combine_fragment
58 | program
59 | doesntexist
60 | draw
61 | DRAW_QUAD
62 | metalVertexShader
63 | red_combine_vertex
64 |
65 | pass_blur_h
66 |
67 | colorStates
68 |
69 | clear
70 |
71 |
72 | inputs
73 |
74 | symbolAsCalledInMetal
75 | customVariableSymbol
76 | maskSampler
77 | MASK
78 |
79 | outputs
80 |
81 | color
82 | MASK
83 |
84 | metalFragmentShader
85 | blue_blur_fragment_h
86 | program
87 | doesntexist
88 | draw
89 | DRAW_QUAD
90 | metalVertexShader
91 | blue_blur_vertex
92 |
93 | pass_red_blur_h
94 |
95 | colorStates
96 |
97 | clear
98 |
99 |
100 | inputs
101 |
102 | symbolAsCalledInMetal
103 | customVariableSymbol
104 | maskSampler
105 | MASK
106 |
107 | outputs
108 |
109 | color
110 | MASK
111 |
112 | metalFragmentShader
113 | red_blur_fragment_h
114 | program
115 | doesntexist
116 | draw
117 | DRAW_QUAD
118 | metalVertexShader
119 | red_blur_vertex
120 |
121 | pass_halo_mask
122 |
123 | inputs
124 |
125 | symbolAsCalledInMetal
126 | customVariableSymbol
127 | colorSampler
128 | COLOR
129 |
130 | outputs
131 |
132 | color
133 | MASK
134 |
135 | metalFragmentShader
136 | red_mask_fragment
137 | program
138 | doesntexist
139 | excludeCategoryMask
140 | 4
141 | draw
142 | DRAW_SCENE
143 | metalVertexShader
144 | red_mask_vertex
145 |
146 | pass_draw_masks
147 |
148 | inputs
149 |
150 | symbolAsCalledInMetal
151 | customVariableSymbol
152 | colorSampler
153 | COLOR
154 |
155 | outputs
156 |
157 | color
158 | MASK
159 |
160 | metalFragmentShader
161 | blue_mask_vertex
162 | program
163 | doesntexist
164 | draw
165 | DRAW_SCENE
166 | metalVertexShader
167 | blue_mask_fragment
168 | includeCategoryMask
169 | 4
170 |
171 | pass_blur_v
172 |
173 | colorStates
174 |
175 | clear
176 |
177 |
178 | inputs
179 |
180 | symbolAsCalledInMetal
181 | customVariableSymbol
182 | maskSampler
183 | MASK
184 |
185 | outputs
186 |
187 | color
188 | MASK
189 |
190 | metalFragmentShader
191 | blue_blur_fragment_v
192 | program
193 | doesntexist
194 | draw
195 | DRAW_QUAD
196 | metalVertexShader
197 | blue_blur_vertex
198 |
199 | pass_combine
200 |
201 | colorStates
202 |
203 | clear
204 |
205 |
206 | inputs
207 |
208 | symbolAsCalledInMetal
209 | customVariableSymbol
210 | colorSampler
211 | COLOR
212 | maskSampler
213 | MASK
214 |
215 | outputs
216 |
217 | color
218 | COLOR
219 |
220 | metalFragmentShader
221 | blue_combine_fragment
222 | program
223 | doesntexist
224 | draw
225 | DRAW_QUAD
226 | metalVertexShader
227 | blue_combine_vertex
228 |
229 |
230 | sequence
231 |
232 | pass_draw_masks
233 | pass_blur_h
234 | pass_blur_v
235 | pass_blur_h
236 | pass_blur_v
237 | pass_combine
238 | pass_halo_mask
239 | pass_red_blur_h
240 | pass_red_blur_v
241 | pass_red_blur_h
242 | pass_red_blur_v
243 | pass_red_combine
244 |
245 | symbols
246 |
247 | customVariableSymbol
248 |
249 | type
250 | float
251 |
252 |
253 | targets
254 |
255 | MASK
256 |
257 | format
258 | rgb
259 | size
260 | 512x512
261 | scaleFactor
262 | 1
263 | type
264 | color
265 |
266 |
267 |
268 |
269 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/SpecialEffects/GlowInTwoColors/GlowRed.metal:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | using namespace metal;
4 | #include
5 | #include
6 |
7 |
8 |
9 |
10 |
11 | struct custom_node_t3 {
12 | float4x4 modelTransform;
13 | float4x4 inverseModelTransform;
14 | float4x4 modelViewTransform;
15 | float4x4 inverseModelViewTransform;
16 | float4x4 normalTransform; // Inverse transpose of modelViewTransform
17 | float4x4 modelViewProjectionTransform;
18 | float4x4 inverseModelViewProjectionTransform;
19 | float2x3 boundingBox;
20 | float2x3 worldBoundingBox;
21 | };
22 |
23 | struct custom_vertex_t
24 | {
25 | float4 position [[attribute(SCNVertexSemanticPosition)]];
26 | float4 normal [[attribute(SCNVertexSemanticNormal)]];
27 | half4 color [[attribute(SCNVertexSemanticColor)]];
28 | float3 boneWeights [[attribute(SCNVertexSemanticBoneWeights)]];
29 | };
30 |
31 | struct out_vertex_t
32 | {
33 | float4 position [[position]];
34 | float2 uv;
35 | };
36 |
37 | typedef struct {
38 | float symbolAsCalledInMetal;
39 | } Uniforms;
40 |
41 |
42 | vertex out_vertex_t red_mask_vertex(custom_vertex_t in [[stage_in]],
43 | constant Uniforms& uniforms [[ buffer(0) ]])
44 | {
45 | out_vertex_t out;
46 | out.position = in.position;
47 | return out;
48 | };
49 |
50 |
51 | fragment half4 red_mask_fragment(out_vertex_t in [[stage_in]],
52 | texture2d colorSampler [[texture(0)]],
53 | constant Uniforms& uniforms [[ buffer(0) ]])
54 | {
55 | constexpr sampler sampler2d(coord::normalized, filter::linear, address::repeat);
56 | return half4(1.0);
57 | };
58 |
59 |
60 | ////////////
61 |
62 | constexpr sampler s = sampler(coord::normalized,
63 | r_address::clamp_to_edge,
64 | t_address::repeat,
65 | filter::linear);
66 |
67 | struct MyNodeBuffer {
68 | float4x4 modelTransform;
69 | float4x4 modelViewTransform;
70 | float4x4 normalTransform;
71 | float4x4 modelViewProjectionTransform;
72 | };
73 |
74 |
75 | vertex out_vertex_t red_combine_vertex(custom_vertex_t in [[stage_in]],
76 | constant Uniforms& uniforms [[ buffer(0) ]])
77 | {
78 | float test = uniforms.symbolAsCalledInMetal;
79 | out_vertex_t out;
80 | out.position = in.position;
81 | out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
82 | return out;
83 | };
84 |
85 |
86 | fragment half4 red_combine_fragment(out_vertex_t vert [[stage_in]],
87 | texture2d colorSampler [[texture(0)]],
88 | texture2d maskSampler [[texture(1)]],
89 | constant Uniforms& uniforms [[ buffer(0) ]])
90 | {
91 | float test = uniforms.symbolAsCalledInMetal;
92 | float4 FragmentColor = colorSampler.sample( s, vert.uv);
93 | float4 maskColor = maskSampler.sample(s, vert.uv);
94 |
95 | // Don't render glow on top of the object itself
96 | if ( maskColor.g > 0.5 ) {
97 | return half4(FragmentColor);
98 | }
99 |
100 | float r = 0.9176470588; // 0.56
101 | float g = 0.2392156863; // 0.84
102 | float b = 0.2666666667; // 0.95
103 |
104 | float3 glowColor = float3(r, g, b);
105 |
106 | float alpha = maskColor.r;
107 | float3 out = FragmentColor.rgb * ( 1.0 - alpha ) + alpha * glowColor;
108 | return half4( float4(out.rgb, 1.0) );
109 | }
110 |
111 | ///// Blur //////
112 |
113 | vertex out_vertex_t red_blur_vertex(custom_vertex_t in [[stage_in]],
114 | constant Uniforms& uniforms [[ buffer(0) ]])
115 | {
116 | float test = uniforms.symbolAsCalledInMetal;
117 | out_vertex_t out;
118 | out.position = in.position;
119 | out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
120 | return out;
121 | };
122 |
123 | // http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
124 | constant float weightConstant = 0.175;
125 | constant float offset[] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
126 | constant float weight[] = { weightConstant, weightConstant, weightConstant, weightConstant, weightConstant }; //{ 0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162 };
127 | constant float bufferSize = 512.0;
128 |
129 | fragment half4 red_blur_fragment_h(out_vertex_t vert [[stage_in]],
130 | texture2d maskSampler [[texture(0)]],
131 | constant Uniforms& uniforms [[ buffer(0) ]])
132 | {
133 | float test = uniforms.symbolAsCalledInMetal;
134 | float4 FragmentColor = maskSampler.sample( s, vert.uv);
135 | float FragmentR = FragmentColor.r * weight[0];
136 |
137 |
138 | for (int i=1; i<5; i++) {
139 | FragmentR += maskSampler.sample( s, ( vert.uv + float2(offset[i], 0.0)/bufferSize ) ).r * weight[i];
140 | FragmentR += maskSampler.sample( s, ( vert.uv - float2(offset[i], 0.0)/bufferSize ) ).r * weight[i];
141 | }
142 | return half4(FragmentR, FragmentColor.g, FragmentColor.b, 1.0);
143 | }
144 |
145 | fragment half4 red_blur_fragment_v(out_vertex_t vert [[stage_in]],
146 | texture2d maskSampler [[texture(0)]],
147 | constant Uniforms& uniforms [[ buffer(0) ]])
148 | {
149 | float test = uniforms.symbolAsCalledInMetal;
150 | float4 FragmentColor = maskSampler.sample( s, vert.uv);
151 | float FragmentR = FragmentColor.r * weight[0];
152 |
153 | for (int i=1; i<5; i++) {
154 | FragmentR += maskSampler.sample( s, ( vert.uv + float2(0.0, offset[i])/bufferSize ) ).r * weight[i];
155 | FragmentR += maskSampler.sample( s, ( vert.uv - float2(0.0, offset[i])/bufferSize ) ).r * weight[i];
156 | }
157 |
158 | return half4(FragmentR, FragmentColor.g, FragmentColor.b, 1.0);
159 |
160 | };
161 |
162 |
163 |
--------------------------------------------------------------------------------
/ArtzyCamera/PieceOfArtzy/Variables/PieceOfArtzyVariables.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PieceOfArtzyVariables.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct DisplayVariableStruct {
12 | var show:Float = 10;
13 |
14 | init(show:Float) {
15 | self.show = show;
16 | }
17 | }
18 |
19 |
20 |
21 | struct strokeTimeVariableStruct {
22 | var loopTime:Float = 10;
23 | var startTime:Float = 0;
24 | var endTime:Float = 5;
25 |
26 | init(loopTime:Float, startTime:Float, endTime:Float) {
27 | self.loopTime = loopTime;
28 | self.startTime = startTime;
29 | self.endTime = endTime;
30 | }
31 | }
32 |
33 | struct timedShaderVariablesStruct {
34 | var loopTime:Float = 0;
35 | var startTime:Float = 0;
36 | var endTime:Float = 0;
37 | var colorR:Float = 0;
38 | var colorB:Float = 0;
39 | var colorG:Float = 0;
40 |
41 | init(loopTime:Float, startTime:Float, endTime:Float, colorR:Float, colorB:Float, colorG:Float) {
42 | self.loopTime = loopTime;
43 | self.startTime = startTime;
44 | self.endTime = endTime;
45 | self.colorR = colorR;
46 | self.colorB = colorB;
47 | self.colorG = colorG;
48 | }
49 | };
50 |
51 | struct blurVariableStruct {
52 | var distanceToNode:Float = 10;
53 |
54 | init(distanceToNode:Float) {
55 | self.distanceToNode = distanceToNode;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ArtzyCamera/Variables/AppVariables.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppVariables.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | var artzyNotificationView:NotificationView = NotificationView();
13 | var artzyNotificationBlimp:NotificationBlimp = NotificationBlimp();
14 |
15 | var screenWidth:CGFloat = CGFloat();
16 | var screenHeight:CGFloat = CGFloat();
17 |
18 | var kArtzyNotificationRect:CGRect = CGRect();
19 | var kArtzMinYLabelLine:CGFloat = CGFloat();
20 |
21 | var kArtzyBlimpDimension:CGFloat = CGFloat();
22 | var kArtzyBlimpBaseRect:CGRect = CGRect();
23 |
24 | var kArtzyNotificationLabelRect:CGRect = CGRect();
25 |
26 | var kArtzyCameraButtonDimension:CGFloat = CGFloat();
27 | var kArtzyCameraButtonMinY:CGFloat = CGFloat();
28 |
29 | var kArtzyResetButtonDimension:CGFloat = CGFloat();
30 | var kArtzyResetButtonMinY:CGFloat = CGFloat();
31 |
32 |
33 | var kArtzyHUDButtonGap:CGFloat = CGFloat();
34 | var kArtzyHUDButtonDimension:CGFloat = CGFloat();
35 | var kArtzyHUDButtonMinY:CGFloat = CGFloat();
36 |
37 |
38 | public func instantiateArtzyVariables() {
39 |
40 | kArtzyHUDButtonDimension = 0.15*screenWidth;
41 | kArtzyHUDButtonGap = 0.048*screenWidth;
42 | kArtzyHUDButtonMinY = kArtzyCameraButtonMinY-kArtzyHUDButtonDimension-kArtzyHUDButtonGap;
43 |
44 | kArtzyCameraButtonDimension = screenWidth*0.2;
45 | kArtzyCameraButtonMinY = screenHeight*0.9-kArtzyCameraButtonDimension;
46 |
47 | kArtzyResetButtonDimension = screenWidth*0.125;
48 | kArtzyResetButtonMinY = screenHeight*0.05+kArtzyHUDButtonGap/2
49 |
50 | kArtzyNotificationRect = CGRect(x: screenWidth*0.25, y: 0, width: screenWidth*0.5, height: screenHeight*0.2)
51 | kArtzMinYLabelLine = screenHeight*0.0625
52 |
53 | kArtzyBlimpDimension = screenHeight*0.025;
54 |
55 | kArtzyBlimpBaseRect = CGRect(x: 0, y: kArtzMinYLabelLine, width: kArtzyBlimpDimension, height: kArtzyBlimpDimension)
56 |
57 | kArtzyNotificationLabelRect = CGRect(x: kArtzyBlimpDimension, y: kArtzMinYLabelLine, width: kArtzyNotificationRect.width-kArtzyBlimpDimension, height: kArtzyNotificationRect.height);
58 | }
59 |
--------------------------------------------------------------------------------
/ArtzyCamera/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // ArtzyCamera
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SceneKit
11 | import ARKit
12 | import Photos
13 | import AVKit
14 |
15 |
16 | protocol ViewControllerDelegate {
17 | func resetTracking();
18 | }
19 |
20 |
21 | class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate, ViewControllerDelegate {
22 |
23 | public var activeArtzyPieces:[NSMutableDictionary] = [NSMutableDictionary]();
24 |
25 | var HUD:UIWindow!
26 | @IBOutlet var sceneView: ARSCNView!
27 |
28 | /// A serial queue for thread safety when modifying the SceneKit node graph.
29 | let updateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! +
30 | ".serialSceneKitQueue")
31 |
32 | /// Convenience accessor for the session owned by ARSCNView.
33 | var session: ARSession {
34 | return sceneView.session
35 | }
36 |
37 | // HIDE STATUS BAR
38 | override var prefersStatusBarHidden: Bool {
39 | return true
40 | }
41 |
42 | override func viewDidLoad() {
43 | super.viewDidLoad()
44 |
45 | print("VIEW DID LOAD");
46 | //Instantiate variables
47 | screenWidth = self.view.frame.width;
48 | screenHeight = self.view.frame.height;
49 | instantiateArtzyVariables();
50 |
51 | // Set the view's delegate
52 | self.sceneView.delegate = self
53 | self.sceneView.session.delegate = self
54 |
55 | // self.sceneView.antialiasingMode = .multisampling4X
56 |
57 | self.HUD = UIWindow(frame: self.view.frame);
58 |
59 | let cameraHUD:CameraHUDViewController = CameraHUDViewController();
60 | cameraHUD.sceneView = self.sceneView;
61 | cameraHUD.viewControllerDelegate = self;
62 | self.HUD.rootViewController = cameraHUD;
63 | self.HUD.rootViewController!.view.alpha = 1;
64 | self.HUD.makeKeyAndVisible()
65 |
66 |
67 |
68 | //Photos
69 | let photos = PHPhotoLibrary.authorizationStatus()
70 | if photos == .notDetermined {
71 | PHPhotoLibrary.requestAuthorization({status in
72 | if status == .authorized{
73 | print("AUthorized");
74 | } else {
75 | print("status ", PHPhotoLibrary.authorizationStatus() );
76 | }
77 | })
78 | }
79 |
80 | AVAudioSession.sharedInstance().requestRecordPermission () {
81 | [unowned self] allowed in
82 | if allowed {
83 | // Microphone allowed, do what you like!
84 |
85 | } else {
86 | // User denied microphone. Tell them off!
87 |
88 | }
89 | }
90 |
91 | }
92 |
93 | override func viewDidAppear(_ animated: Bool) {
94 | super.viewDidAppear(animated)
95 |
96 | // Prevent the screen from being dimmed to avoid interuppting the AR experience.
97 | UIApplication.shared.isIdleTimerDisabled = true
98 |
99 | // Start the AR experience
100 | resetTracking()
101 |
102 | }
103 |
104 |
105 | override func viewWillDisappear(_ animated: Bool) {
106 | super.viewWillDisappear(animated)
107 |
108 | // Pause the view's session
109 | self.sceneView.session.pause()
110 | }
111 |
112 | override func didReceiveMemoryWarning() {
113 | super.didReceiveMemoryWarning()
114 | // Release any cached data, images, etc that aren't in use.
115 | }
116 |
117 | // MARK: - Session management (Image detection setup)
118 |
119 | /// Prevents restarting the session while a restart is in progress.
120 | var isRestartAvailable = true
121 |
122 | /// Creates a new AR configuration to run on the `session`.
123 | /// - Tag: ARReferenceImage-Loading
124 | public func resetTracking() {
125 |
126 | print("RESET TRACKING");
127 |
128 | guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
129 | fatalError("Missing expected asset catalog resources.")
130 | }
131 |
132 | let configuration = ARWorldTrackingConfiguration()
133 | configuration.detectionImages = referenceImages
134 | session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
135 |
136 | // REMOVE ALL OBJECTS
137 | self.sceneView.scene.rootNode.enumerateChildNodes { (node, _) in
138 | node.removeFromParentNode();
139 | }
140 | }
141 |
142 | // MARK: - ARSCNViewDelegate (Image detection results)
143 | /// - Tag: ARImageAnchor-Visualizing
144 | func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
145 | guard let imageAnchor = anchor as? ARImageAnchor else { return }
146 | let referenceImage = imageAnchor.referenceImage
147 |
148 | print("REGISTERED IMAGE : \(referenceImage)");
149 |
150 | updateQueue.async {
151 |
152 | let pieceOfArtzy:PieceOfArtzy = PieceOfArtzy();
153 | pieceOfArtzy.sceneView = self.sceneView;
154 | // artzyPiece.artzyHUD = self.artzyHUD;
155 | pieceOfArtzy.node = node;
156 | pieceOfArtzy.referenceImage = referenceImage;
157 | pieceOfArtzy.start();
158 |
159 | let ArtzyPieces:NSMutableDictionary = [
160 | "node" : node,
161 | "pieceOfArtzy" : pieceOfArtzy,
162 | "withinPointOfView": false,
163 | "distanceToObject": 0
164 | ]
165 |
166 | self.activeArtzyPieces.append(ArtzyPieces);
167 |
168 |
169 | }
170 | }
171 |
172 | func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
173 | // print("OPEN GL CONTEXT \(self.sceneView)" )
174 |
175 | DispatchQueue.main.async {
176 |
177 | (self.HUD.rootViewController as! CameraHUDViewController).didUpdateAtTime(time:time);
178 |
179 | }
180 |
181 | }
182 |
183 | func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
184 | for ArtzyDict in self.activeArtzyPieces {
185 | let pieceOfArtzy:PieceOfArtzy = ArtzyDict.value(forKey: "pieceOfArtzy") as! PieceOfArtzy;
186 | pieceOfArtzy.didUpdateAtTime();
187 | }
188 | }
189 |
190 | var imageHighlightAction: SCNAction {
191 | return .sequence([
192 | .wait(duration: 0.25),
193 | .fadeOpacity(to: 0.85, duration: 0.25),
194 | .fadeOpacity(to: 0.15, duration: 0.25),
195 | .fadeOpacity(to: 0.85, duration: 0.25),
196 | .fadeOut(duration: 0.5),
197 | .removeFromParentNode()
198 | ])
199 | }
200 |
201 |
202 |
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/ArtzyCamera/art.scnassets/localxAdamfu.scn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/ArtzyCamera/art.scnassets/localxAdamfu.scn
--------------------------------------------------------------------------------
/ArtzyCameraTests/ArtzyCameraTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArtzyCameraTests.swift
3 | // ArtzyCameraTests
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import ArtzyCamera
11 |
12 | class ArtzyCameraTests: XCTestCase {
13 |
14 | override func setUp() {
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | }
21 |
22 | func testExample() {
23 | // This is an example of a functional test case.
24 | // Use XCTAssert and related functions to verify your tests produce the correct results.
25 | }
26 |
27 | func testPerformanceExample() {
28 | // This is an example of a performance test case.
29 | self.measure {
30 | // Put the code you want to measure the time of here.
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/ArtzyCameraTests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ArtzyCameraUITests/ArtzyCameraUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArtzyCameraUITests.swift
3 | // ArtzyCameraUITests
4 | //
5 | // Created by Oscar De la Hera Gomez on 12/3/18.
6 | // Copyright © 2018 Delasign. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class ArtzyCameraUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 |
16 | // In UI tests it is usually best to stop immediately when a failure occurs.
17 | continueAfterFailure = false
18 |
19 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
20 | XCUIApplication().launch()
21 |
22 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
23 | }
24 |
25 | override func tearDown() {
26 | // Put teardown code here. This method is called after the invocation of each test method in the class.
27 | }
28 |
29 | func testExample() {
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/ArtzyCameraUITests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/GettingStarted/Hand-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/GettingStarted/Hand-02.png
--------------------------------------------------------------------------------
/GettingStarted/a4Logo-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/GettingStarted/a4Logo-01.png
--------------------------------------------------------------------------------
/GettingStarted/adamLocal-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/GettingStarted/adamLocal-01.png
--------------------------------------------------------------------------------
/HowItWasMade/Hand/Files/hand.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Hand/Files/hand.mb
--------------------------------------------------------------------------------
/HowItWasMade/Hand/Image/Hand-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Hand/Image/Hand-02.png
--------------------------------------------------------------------------------
/HowItWasMade/Loader/Files/Loading.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Loader/Files/Loading.mb
--------------------------------------------------------------------------------
/HowItWasMade/Loader/Files/logo.scn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Loader/Files/logo.scn
--------------------------------------------------------------------------------
/HowItWasMade/Loader/Image/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Loader/Image/1024.png
--------------------------------------------------------------------------------
/HowItWasMade/Local/Files/adamLocalFinal.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Local/Files/adamLocalFinal.mb
--------------------------------------------------------------------------------
/HowItWasMade/Local/Image/adamLocal-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/delasign/ArtzyCamera/af6ae64d257b12e4e5436c575a2e1c775572cae2/HowItWasMade/Local/Image/adamLocal-01.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Open Source Artzy™ Camera
2 |
3 | The Open Source Artzy™ Camera is an ARKit super-starter project created by Delasign that features an AR multi-media recorder, 3 AR samples, a library of free metal shaders and special effects, illustrator and maya files.
4 |
5 |
6 |
7 | # Sharing is caring.
8 |
9 | If you create anything, please share it on Instagram and tag @artzyapp along with #artzy.
10 |
11 |
12 | # Getting started
13 | Download the repo and print the three images in the "GettingStarted" folder. These are the three AR samples that come with the project.
14 |
15 | After printing, open the app and place your phone infront of the images to experience the three samples.
16 |
17 | # Ok, I want to start creating.
18 | I recommend reading up on AR and ARKit before becoming familiar with how the samples were created. These are found in the "HowItWasMade" folder, which includes the files that were used and the corresponding images.
19 |
20 | If you have any questions please email questions to : artzy@delasign.com
21 |
22 | # Recommended reading
23 |
24 | For all posts ever, please visit my blog.
25 |
26 | Apple Documentation:
27 |
28 | - ARKit
29 | - Building your first ARKit Experience
30 |
31 |
32 | - AR World Tracking Configuration
33 | - Understanding World Tracking in ARKit
34 |
35 | - ARReferenceImages
36 | - ARImageAnchor
37 | - Recognizing Images in an AR Experience
38 |
39 |
40 | - ARFrame
41 | - ARCamera
42 |
43 |
44 | - SceneKit
45 | - SCNNode
46 | - SCNProgram
47 | - SCNTechnique
48 |
49 | ARKit Theory:
50 |
51 | - The Point Cloud, Image Recognition, AR Ready Images, True Scale, The Renderer and Nodes
52 | - Vertices, Metal Shaders, UV Mapping and SCNProgram’s.
53 | - ARCamera POV.
54 | - Intro to SCNTechniques.
55 |
56 |
57 | # Sample projects
58 |
59 | The repository comes with three opensource AR samples, which are detailed below.
60 |
61 | ## 'local' by adamfu x delasign
62 |
63 |
64 |
65 | This project features a double neon glow - the word glows in blue, whilst the halo glows in red.
66 |
67 | For tutorials on how this was created please read the following:
68 |
69 | Geometry:
70 |
71 | - How to use an Adobe Illustrator Curve in Maya.
72 | - How to turn a turn a simple sketch into an extruded model on Maya
73 | - UV Mapping: How to Convert an Extruded Cylinder’s UV’s to Simple Layout
74 |
75 | Neon:
76 |
77 | - Apple Documentation : SCNTechnique
78 | - ARKit Theory: Intro to SCNTechniques.
79 | - How to create a glowing neon effect for a geometry in ARKit through a SCN Technique
80 | - A SCNTechnique requires a .scn model
81 |
82 |
83 | Code:
84 |
85 | The key parts to this working are found in *PieceOfArtzy/PieceOfArtzy.swift* line 182 -> 264, with the SCNTechnique and associated assets under the *PieceOfArtzy/SpecialEffects/GlowInTwoColors* folder.
86 |
87 | Extra:
88 | To see it perform an animated, timed stroke - switch the functionality in *PieceOfArtzy/PieceOfArtzy.swift* line 34.
89 |
90 | ## 'loader' by delasign
91 |
92 |
93 |
94 | This project features a 3d stroke neon glow - it appears as though the word has been drawn.
95 |
96 | For tutorials on how this was created please read the following:
97 |
98 | Geometry:
99 |
100 | - How to use an Adobe Illustrator Curve in Maya.
101 | - How to turn a turn a simple sketch into an extruded model on Maya
102 | - UV Mapping: How to Convert an Extruded Cylinder’s UV’s to Simple Layout
103 |
104 | Neon:
105 |
106 | - Apple Documentation : SCNTechnique
107 | - ARKit Theory: Intro to SCNTechniques.
108 | - How to create a glowing neon effect for a geometry in ARKit through a SCN Technique
109 | - How to connect custom variables to SCNTechniques and Associated Metal Shaders
110 | - A SCNTechnique requires a .scn model
111 |
112 | Stroke:
113 | The key parts to this working are found in *PieceOfArtzy/PieceOfArtzy.swift* line 66 -> 92. The amount of the letter that must be shown at any given instance has to be programmed in order for the camera to be able to capture it. For a non-capturable version and how to take it from there to the latest version, please read:
114 |
115 | - Free Stroke Metal Shader on a Timer
116 |
117 | - ARKit Tutorial: How to attach Custom Variables to a Metal Shader & its associated SCNProgram through a TimedStroke Shader iOS 12.
118 |
119 | - How to connect custom variables to SCNTechniques and Associated Metal Shaders
120 |
121 |
122 | Code:
123 |
124 | The key parts to this working are found in *PieceOfArtzy/PieceOfArtzy.swift* line 264 -> 312, with the SCNTechnique and associated assets under the *PieceOfArtzy/SpecialEffects/Glow* folder.
125 |
126 |
127 | ## 'hand' by delasign
128 |
129 |
130 |
131 | This project features an outline of a hand that animates to show you the peace sign.
132 |
133 | For tutorials on how this was created please read the following:
134 |
135 | Geometry:
136 |
137 | - How to use an Adobe Illustrator Curve in Maya.
138 | - How to turn a turn a simple sketch into an extruded model on Maya
139 | - UV Mapping: How to Convert an Extruded Cylinder’s UV’s to Simple Layout
140 |
141 | Animation:
142 | Please note that the key to this is to only rotate the joints.
143 |
144 | - How to make an animtion in Maya that works in SceneKit or ARKit.
145 |
146 | - Maya Weight Painting Tutorial
147 |
148 | Code:
149 |
150 | The key parts to this working are found in *PieceOfArtzy/PieceOfArtzy.swift* line 41 -> 59.
151 |
152 |
153 | # Shader library
154 | If you are new to Shaders please read this: Vertices, Metal Shaders, UV Mapping and SCNProgram’s.
155 |
156 | The current shader library can be found in *PieceOfArtzy/Shaders* and includes:
157 |
158 | - Color Shader
159 | - Texture Shader
160 | - Stroke Shader
161 | - Backwards Stroke Shader
162 | - Timed Stroke Shader
163 | - Timed Backwards Stroke Shader
164 | - Fade In Color Shader
165 | - Fade In Texture Shader
166 |
167 |
168 |
169 | # License
170 | MIT License
171 |
172 | Copyright (c) 2018 Delasign LLC.
173 |
174 | Permission is hereby granted, free of charge, to any person obtaining a copy
175 | of this software and associated documentation files (the "Software"), to deal
176 | in the Software without restriction, including without limitation the rights
177 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
178 | copies of the Software, and to permit persons to whom the Software is
179 | furnished to do so, subject to the following conditions:
180 |
181 | The above copyright notice and this permission notice shall be included in all
182 | copies or substantial portions of the Software.
183 |
184 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
185 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
187 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
188 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
189 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
190 | SOFTWARE.
191 |
192 | ## Artzy™ Logo
193 |
194 | Created by AdamFu under the and licensed under the Creative Commons Attribution 4.0 International License.
195 |
196 |
197 |
198 |
199 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Delasign LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------