使用 SceneKit/Swift 将 worldPosition 转换为 SceneView 位置

发布于 2025-01-12 01:04:08 字数 3279 浏览 0 评论 0原文

iOS 15,Swift 5

我试图让 sceneView [SwiftUI SceneKit 插件] 在我的场景中添加/查找节点。我感觉我已经快到了,但其实还没有。

遗憾的是,这里的 hit 函数什么也没找到,这就是我最终将其注释掉的原因。之后我尝试使用projectPoint,但结果没有意义?

现在我确实使用 UIViewRespresentable 完成了这项工作,但该解决方案根本不使用 sceneView。

我想将拖动坐标转换为 SCNView 坐标,因为我认为我可以找到/匹配对象。

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)")
//    }
  }

  }

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)")
//    }
  }

  }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文