我有以下情况。一个SCNView带着.scn一座桥的展示。在屏幕的左边,你可以看到桥的视觉表现形式。
我想做以下几件事。
在“模型浏览器”中选择左边的项 缩放到选定的项目并将焦点集中在它上。 https://i.stack.imgur.com/OBDbi.png
在提供的截图上。你可以看到我选择了Kist是黄色的SceneView现在我想放大并聚焦在选定的SCNNode
我已经试过用rayTestWithSegment若要找到要缩放的选定位置,请执行以下操作。但结果rayTestWithSegment总是[].
我也试过用SCNLookAtConstraint但这不管用。
var constraint: SCNLookAtConstraint!
func handle(gesture: UIGestureRecognizer) {
guard let result = hitTestResult(for: gesture), let world = sceneView?.scene?.physicsWorld else { return }
let nodePosition = result.node.position
let results = world.rayTestWithSegment(from: SCNVector3(0, 1, 0), to: nodePosition, options: nil)
print(results)
constraint = SCNLookAtConstraint(target: result.node)
sceneView?.pointOfView?.constraints = [constraint]
}
func hitTestResult(for gesture: UIGestureRecognizer) -> SCNHitTestResult? {
let location = gesture.location(in: sceneView)
guard let hit = sceneView?.hitTest(location, options: nil), hit.count > 0, let result = hit.first else {
return nil
}
return result
}
我在用rayTestWithSegment因为有可能SCNNode我选择的不是完全可见的。例如,一个SCNNode它位于此透视图中的另一个节点后面。
提前谢谢,我希望有人能帮我解释我做错了什么。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
根据你的描述,你希望在SceneKit中实现点击屏幕上的3D模型节点后,场景视图能够自动缩放并聚焦到被选中的节点上。从你的代码片段来看,有几个地方可能需要调整:
使用hitTest(_:options:)
而非自定义的hitTestResult(for:)
: 你的hitTestResult(for:)
方法看起来是正确的,但直接使用sceneView.hitTest(location, options: nil)
应该已经足够处理触摸事件并获取到击中的节点。
理解rayTestWithSegment
的用途: rayTestWithSegment
用于物理检测,即判断射线与物理体的碰撞,而不是用于找到一个可见或不可见的SCNNode。如果你的目标是找到用户点击位置对应的节点,你应该继续使用hitTest(_:options:)
。
使用SCNLookAtConstraint
正确聚焦: 你的SCNLookAtConstraint
应用方式基本正确,但是确保以下几点:
pointOfView
不为nil。这是执行观察操作的虚拟相机节点。GAFFER_lookAtUp
, GAFFER_lookAtRight
等属性来微调视角。缩放和平移场景: 要缩放和平移到选定节点,你可以直接修改cameraNode
的位置和缩放属性,或者使用动画平滑过渡。例如,你可以计算从当前相机位置到目标节点的最佳距离和方向,然后用动画来实现这一变化。
修正后的代码示例(注意:此代码未经过实际测试,仅提供思路):
@objc func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
let location = gestureRecognizer.location(in: sceneView)
if let hit = sceneView.hitTest(location, options: [.searchMode: .allHierarchies]).first {
// 获取点击的节点
let selectedNode = hit.node
// 使用SCNLookAtConstraint聚焦
let constraint = SCNLookAtConstraint(target: selectedNode)
constraint.isGimbalLockEnabled = true // 可选,防止旋转异常
sceneView.pointOfView?.constraints = [constraint]
// 动画平滑聚焦和缩放
let distance = sceneView.pointOfView?.position.distance(to: selectedNode.position) ?? 0
let newCameraPosition = SCNVector3(selectedNode.position.x, selectedNode.position.y + distance * 1.5, selectedNode.position.z) // 调整距离以适应视图
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = sceneView.pointOfView?.position
animation.toValue = newCameraPosition
animation.duration = 0.5
sceneView.pointOfView?.addAnimation(animation, forKey: "focusOnNode")
}
}
请根据你的具体需求调整上述代码,比如动画时间、相机的新位置计算逻辑等。希望这能帮助你解决问题!