'Converting worldPosition into a SceneView position with SceneKit/Swift
iOS 15, Swift 5
I am trying to get sceneView [SwiftUI SceneKit plugin] to work with adding/finding nodes within my scene. And I feel I am almost there and yet I am not.
Sadly the hits function here finds nothing, which is why I ended up commenting it out. I tried used projectPoint after that, but the results make no sense?
Now I did get this working using UIViewRespresentable, but that solution doesn't use sceneView at all.
I want to convert the drag coordinates to the SCNView coordinates since since I think I can find/match objects.
import SwiftUI
import SceneKit
struct ContentView: View {
let settings = SharedView.shared
var (scene,cameraNode) = GameScene.shared.makeView()
var body: some View {
GameView(scene: scene, cameraNode: cameraNode)
}
}
struct GameView: View {
let settings = SharedView.shared
@State var scene: SCNScene
@State var cameraNode: SCNNode
var body: some View {
SceneView(
scene: scene,
pointOfView: cameraNode,
options: [.autoenablesDefaultLighting, .rendersContinuously ], delegate: SceneDelegate())
.gesture(DragGesture(minimumDistance: 0)
.onChanged({ gesture in
settings.location = gesture.location
}).sequenced(before: TapGesture().onEnded({ _ in
GameScene.shared.tapV()
}))
)
}
}
class SharedView: ObservableObject {
@Published var location:CGPoint!
@Published var view:UIView!
@Published var scene:SCNScene!
@Published var sphereNode:SCNNode!
static var shared = SharedView()
}
@MainActor class SceneDelegate: NSObject, SCNSceneRendererDelegate {
}
class GameScene: UIView {
static var shared = GameScene()
let settings = SharedView.shared
var view: SCNView!
var scene: SCNScene!
func makeView() -> (SCNScene,SCNNode) {
let material = SCNMaterial()
material.diffuse.contents = UIColor.red
let sphere = SCNSphere(radius: 1.0)
sphere.materials = [material]
let sphereNode = SCNNode()
sphereNode.geometry = sphere
sphere.name = "sphereNode"
let camera = SCNCamera()
camera.fieldOfView = 90.0
let light = SCNLight()
light.color = UIColor.white
light.type = .omni
let cameraNode = SCNNode()
cameraNode.simdPosition = SIMD3<Float>(0.0, 0.0, 6)
cameraNode.camera = camera
cameraNode.light = light
scene = SCNScene()
scene.background.contents = UIColor.black
scene.rootNode.addChildNode(sphereNode)
scene.rootNode.addChildNode(cameraNode)
view = SCNView()
view.scene = scene
view.pointOfView = cameraNode
settings.sphereNode = sphereNode
return (scene, cameraNode)
}
func tapV() {
let location = settings.location
let hits = view.hitTest(location!, options: [.boundingBoxOnly: true, .firstFoundOnly: true, .searchMode: true])
print("hits \(hits.count)")
// for hit in hits {
let material = SCNMaterial()
material.diffuse.contents = UIColor.yellow
let geometry = SCNSphere(radius: 0.1)
geometry.materials = [material]
let node = SCNNode()
node.geometry = geometry
// node.simdPosition = hit.simdWorldCoordinates
let projectedOrigin = view.projectPoint(SCNVector3Zero)
var worldPoint = view.unprojectPoint(SCNVector3(location!.x, location!.y, CGFloat(0)))
node.worldPosition = worldPoint
view.scene!.rootNode.addChildNode(node)
print("node \(node.position) \(hits.count)")
// }
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
