-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SwiftUI visionOS example. #115
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
5b4b257
add visionOS sample
halmueller f05ec2c
swiftformat
halmueller 50e24a8
update README
halmueller 6971897
Remove ImmersiveView boilerplate.
halmueller 6840412
Remove ImmersiveView boilerplate.
halmueller 661b760
Correct comment
halmueller afaec04
Nicer scaling
halmueller File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
12 changes: 12 additions & 0 deletions
12
...xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "vision", | ||
"scale" : "2x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
...eVisionOS/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
ExampleVisionOS/Assets.xcassets/AppIcon.solidimagestack/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
}, | ||
"layers" : [ | ||
{ | ||
"filename" : "Front.solidimagestacklayer" | ||
}, | ||
{ | ||
"filename" : "Middle.solidimagestacklayer" | ||
}, | ||
{ | ||
"filename" : "Back.solidimagestacklayer" | ||
} | ||
] | ||
} |
12 changes: 12 additions & 0 deletions
12
...cassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "vision", | ||
"scale" : "2x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
...VisionOS/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...assets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "vision", | ||
"scale" : "2x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
...isionOS/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// ContentView.swift | ||
// ExampleVisionOS | ||
// | ||
// Created by Hal Mueller on 3/5/24. | ||
// Copyright © 2024 Nick Lockwood. All rights reserved. | ||
// | ||
|
||
import RealityKit | ||
import SwiftUI | ||
|
||
struct ContentView: View { | ||
@State private var enlarge = false | ||
|
||
var body: some View { | ||
VolumetricView() | ||
} | ||
} | ||
|
||
#Preview(windowStyle: .volumetric) { | ||
ContentView() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// EuclidMesh.swift | ||
// ExampleVisionOS | ||
// | ||
// Created by Hal Mueller on 3/5/24. | ||
// Copyright © 2024 Nick Lockwood. All rights reserved. | ||
// | ||
|
||
import CoreGraphics | ||
import Euclid | ||
|
||
let euclidMesh: Mesh = { | ||
let start = CFAbsoluteTimeGetCurrent() | ||
|
||
// create some geometry using Euclid | ||
let cube = Mesh.cube(size: 0.8, material: Color.red) | ||
let sphere = Mesh.sphere(slices: 120, material: CGImage.checkerboard()) | ||
let mesh = cube.subtracting(sphere).makeWatertight() | ||
|
||
print("Time:", CFAbsoluteTimeGetCurrent() - start) | ||
print("Polygons:", mesh.polygons.count) | ||
print("Triangles:", mesh.triangulate().polygons.count) | ||
print("Watertight:", mesh.isWatertight) | ||
|
||
return mesh | ||
}() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// ExampleVisionOSApp.swift | ||
// ExampleVisionOS | ||
// | ||
// Created by Hal Mueller on 3/5/24. | ||
// Copyright © 2024 Nick Lockwood. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
|
||
@main | ||
struct ExampleVisionOSApp: App { | ||
var body: some Scene { | ||
WindowGroup { | ||
ContentView() | ||
} | ||
.windowStyle(.volumetric) | ||
.defaultSize(width: 1.5, height: 1.5, depth: 1.5, in: .meters) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>UIApplicationSceneManifest</key> | ||
<dict> | ||
<key>UIApplicationPreferredDefaultSceneSessionRole</key> | ||
<string>UIWindowSceneSessionRoleVolumetricApplication</string> | ||
<key>UIApplicationSupportsMultipleScenes</key> | ||
<true/> | ||
<key>UISceneConfigurations</key> | ||
<dict/> | ||
</dict> | ||
</dict> | ||
</plist> |
6 changes: 6 additions & 0 deletions
6
ExampleVisionOS/Preview Content/Preview Assets.xcassets/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// | ||
// VolumetricView.swift | ||
// ExampleVisionOS | ||
// | ||
// Created by Hal Mueller on 3/6/24. | ||
// Copyright © 2024 Nick Lockwood. All rights reserved. | ||
// | ||
|
||
import RealityKit | ||
import SwiftUI | ||
|
||
struct VolumetricView: View { | ||
@State private var spinX = 0.0 | ||
@State private var spinY = 0.0 | ||
|
||
var body: some View { | ||
RealityView { content in | ||
if let demoBoxEntity = try? ModelEntity(euclidMesh.scaled(by: 0.5)) { | ||
// for more realism, add a shadow | ||
demoBoxEntity.components.set(GroundingShadowComponent(castsShadow: true)) | ||
|
||
// needed for tap detection/response | ||
demoBoxEntity.generateCollisionShapes(recursive: true) | ||
|
||
// for gesture targeting | ||
demoBoxEntity.components.set(InputTargetComponent()) | ||
|
||
content.add(demoBoxEntity) | ||
} | ||
} update: { content in | ||
guard let entity = content.entities.first else { return } | ||
|
||
let pitch = Transform(pitch: Float(spinX * -1)).matrix | ||
let yaw = Transform(yaw: Float(spinY)).matrix | ||
entity.transform.matrix = pitch * yaw | ||
} | ||
.gesture( | ||
DragGesture(minimumDistance: 0) | ||
.targetedToAnyEntity() | ||
.onChanged { value in | ||
let startLocation = value.convert(value.startLocation3D, from: .local, to: .scene) | ||
let currentLocation = value.convert(value.location3D, from: .local, to: .scene) | ||
let delta = currentLocation - startLocation | ||
spinX = Double(delta.y) * 5 | ||
spinY = Double(delta.x) * 5 | ||
} | ||
) | ||
} | ||
} | ||
|
||
#Preview { | ||
VolumetricView() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this PR is closed, but (and maybe this is the wrong place to ask this question), I'm curious how important
makeWatertight()
is here.When running this on device as/is, the print of
Time:
was ~4.5 seconds. If I remove the call tomakeWatertight()
and bump the sphere slices parameter down to 60, it runs in around .5 seconds, and there doesn't seem (to me) to be a discernible difference.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mgrider Are you sure it wasn't reducing the slices that had the main impact, not removing makeWatertight()? The latter is usually negligible.
In any case, the answer is that non-watertight shapes can cause weird artifacts when performing CSG operations, but in this case since it's the last step you can skip it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better improvement might be to get the construction off the main thread with a Task.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I almost forgot, if you are running in debug mode, switching to release mode (or just enabling optimized builds for the Euclid module in debug mode, which will still let you debug the example app) should yield a significant speedup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're totally right. Adding
makeWatertight()
back yields:Time: 0.6943490505218506
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it's just my opinion, but I think a 4.5 second delay in the example project feels broken (or at least not especially great), whereas .5 gets a 🤷♂️. Of course there will be ways to optimize, but this is going to be what people see when they're evaluating Euclid as a dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love that this got made/merged, BTW. Definitely aiming for (hopefully helpful) constructive criticism!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's still a problem with blocking the main thread. What I had missed earlier is that Apple's RK samples all use the
try! await Entity(named: "MyEntity")
idiom, calling the async method to load from a file. There is no async version ofinit(_ mesh:...)
, so we should be calling that in a task and adding the content when it's ready. A real-world user of the framework may have very complicated/expensive meshes to build. Let me poke at that a bit and I'll post a new PR/branch.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything in Euclid should be safe to run on a background thread. Distinct meshes should be safe to create in parallel on multiple threads/tasks as there's no global shared state.
Euclid already makes some use of multithreading internally which may not play nicely with async/await but is probably OK. Search for "batch" in the codebase if you're curious.
I plan to add async interfaces at some point, but it's complicated for various reasons. You're more than welcome to take a stab at it if you like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See what we think about #116. And let's continue conversation on that PR, close out this thread.