如何在SceneKit中在用户点击位置渲染球体?

huangapple go评论108阅读模式
英文:

How to render spheres in SceneKit at user's tap position?

问题

我正在使用Swift和SceneKit开发iOS应用程序。当用户点击屏幕时,我希望在SceneKit中的用户点击位置渲染一个点。我该如何实现这个功能?

我正在使用unprojectPoint()方法,但是我的对象没有渲染在预期的位置。

我有一个SceneView,摄像机设置如下:

  1. cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

然后,我通过以下方式在点击位置渲染点:

  1. func handleTap(_ gestureRecognize: UIGestureRecognizer) {
  2. // 获取SCNView
  3. let scnView = self.view as! SCNView
  4. // 创建点
  5. let geo = SCNSphere(radius: CGFloat(0.1))
  6. geo.firstMaterial?.diffuse.contents = UIColor.red
  7. let dotNode = SCNNode(geometry: geo)
  8. let p = gestureRecognize.location(in: scnView)
  9. let uP = scnView.unprojectPoint(SCNVector3(p.x, p.y, 5))
  10. // 在这里 - 如何设置点的位置?
  11. dotNode.position = SCNVector3(uP.x, uP.y, 5)
  12. scnView.scene?.rootNode.addChildNode(dotNode)
  13. }

这是我的Github仓库链接:https://github.com/rudyhuynh/SceneKitExample

英文:

I am working on an iOS app with Swift and SceneKit. When user taps on screen, I want to render a dot in SceneKit at the location that user just tapped. How can I do that?

I am using unprojectPoint() method but my object is not rendered at expected location.

I am having a SceneView, with the camera like this:

  1. cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

And then I render the dot at tap position like this:

  1. func handleTap(_ gestureRecognize: UIGestureRecognizer) {
  2. // retrieve the SCNView
  3. let scnView = self.view as! SCNView
  4. // create dot
  5. let geo = SCNSphere(radius: CGFloat(0.1))
  6. geo.firstMaterial?.diffuse.contents = UIColor.red
  7. let dotNode = SCNNode(geometry: geo)
  8. let p = gestureRecognize.location(in: scnView)
  9. let uP = scnView.unprojectPoint(SCNVector3(p.x, p.y, 5))
  10. // HERE - how to set position for the dot ?
  11. dotNode.position = SCNVector3(uP.x, uP.y, 5)
  12. scnView.scene?.rootNode.addChildNode(dotNode)
  13. }

Here is my Github repo: https://github.com/rudyhuynh/SceneKitExample

答案1

得分: 1

反投影一个点

为了在预期位置渲染点节点,请使用以下方法。不要忘记你正在使用透视投影查看场景。对具有 Z 坐标为 0.0 的点进行反投影会返回位于近裁剪平面上的点。对具有 Z 坐标为 1.0 的点进行反投影会返回位于远裁剪平面上的点。

  1. import SceneKit
  2. class GameViewController: UIViewController {
  3. override func viewDidLoad() {
  4. super.viewDidLoad()
  5. let sceneView = self.view as! SCNView
  6. sceneView.scene = SCNScene()
  7. sceneView.backgroundColor = UIColor.black
  8. let cameraNode = SCNNode()
  9. cameraNode.camera = SCNCamera()
  10. cameraNode.simdPosition = simd_float3(0, 0, 1)
  11. sceneView.scene?.rootNode.addChildNode(cameraNode)
  12. let tapGesture = UITapGestureRecognizer(target: self,
  13. action: #selector(tap))
  14. sceneView.addGestureRecognizer(tapGesture)
  15. }
  16. @objc func tap(_ gestureRecognizer: UITapGestureRecognizer) {
  17. let scnView = self.view as! SCNView
  18. let geo = SCNSphere(radius: 0.01)
  19. geo.firstMaterial?.diffuse.contents = UIColor.white
  20. let dotNode = SCNNode(geometry: geo)
  21. let point = gestureRecognizer.location(in: scnView)
  22. let unprojected = scnView.unprojectPoint(.init(point.x, point.y, 0))
  23. dotNode.position = SCNVector3(unprojected.x, unprojected.y, -0.01)
  24. scnView.scene?.rootNode.addChildNode(dotNode)
  25. }
  26. }

要在正交投影下运行相机,请使用:

  1. cameraNode.camera?.usesOrthographicProjection = true
英文:

Unprojecting a Point

To render dot nodes at expected position, use the following approach. Don't forget that you are looking at the scene in perspective projection. Unprojecting a point whose Z-coordinate is 0.0 returns a point on the near clipping plane. Unprojecting a point whose Z-coordinate is 1.0 returns a point on the far clipping plane.

  1. import SceneKit
  2. class GameViewController: UIViewController {
  3. override func viewDidLoad() {
  4. super.viewDidLoad()
  5. let sceneView = self.view as! SCNView
  6. sceneView.scene = SCNScene()
  7. sceneView.backgroundColor = UIColor.black
  8. let cameraNode = SCNNode()
  9. cameraNode.camera = SCNCamera()
  10. cameraNode.simdPosition = simd_float3(0, 0, 1)
  11. sceneView.scene?.rootNode.addChildNode(cameraNode)
  12. let tapGesture = UITapGestureRecognizer(target: self,
  13. action: #selector(tap))
  14. sceneView.addGestureRecognizer(tapGesture)
  15. }
  16. @objc func tap(_ gestureRecognizer: UITapGestureRecognizer) {
  17. let scnView = self.view as! SCNView
  18. let geo = SCNSphere(radius: 0.01)
  19. geo.firstMaterial?.diffuse.contents = UIColor.white
  20. let dotNode = SCNNode(geometry: geo)
  21. let point = gestureRecognizer.location(in: scnView)
  22. let unprojected = scnView.unprojectPoint(.init(point.x, point.y, 0))
  23. dotNode.position = SCNVector3(unprojected.x, unprojected.y, -0.01)
  24. scnView.scene?.rootNode.addChildNode(dotNode)
  25. }
  26. }

如何在SceneKit中在用户点击位置渲染球体?

To run a camera in orthographic projection, use:

  1. cameraNode.camera?.usesOrthographicProjection = true

huangapple
  • 本文由 发表于 2023年6月14日 23:29:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76475229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定