gpt4 book ai didi

ios - SceneKit: HitTest 不适用于广告牌四边形

转载 作者:行者123 更新时间:2023-11-30 13:00:36 28 4
gpt4 key购买 nike

我使用 SceneKit 制作了广告牌四边形。cameraNode 与 UIDeviceMotion 同步,并且广告牌节点按我的预期出现。问题是,我希望在点击这些节点时调用它们。为此,我使用了 UITapGestureRecognizer 和 hitTest。这是我的一些代码。

// ==== in viewDidLoad

// initialize tap gesture
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onNodeTapped))
sceneView.addGestureRecognizer(tapGesture)

// initialize scenekit.scene
let scene = SCNScene()
scene.rootNode.addChildNode(cameraNode)
scene.rootNode.addChildNode(worldNode)
sceneView.scene = scene
sceneView.autoenablesDefaultLighting = true
sceneView.pointOfView = cameraNode

这是点击处理程序

func onNodeTapped(_ gestureRecognize: UIGestureRecognizer) {
let location = gestureRecognize.location(in: sceneView) // <---- updated
let hitResults = sceneView.hitTest(location, options: nil)
for result in hitResults {
// FOR_TEST: hit test visualization
if let material = result.node.geometry?.materials.first {
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5
SCNTransaction.completionBlock = {
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5
material.emission.contents = UIColor.black
SCNTransaction.commit()
}
material.emission.contents = UIColor.red
SCNTransaction.commit()
}

// target tap event handling
if let target = (result.node as? TargetNode)?.target {
if onTargetTapped(target) {
return
}
}
}
}

这段代码很少能工作。我的意思是可视化部分只响应 20 次中的 1 次,而 onTargetTapped 只被调用 100 次中的 1 次......奇怪的是定位没问题,这意味着这不是坐标问题。

我找到了与 SCNHitTestOption.categoryBitMask 相关的内容,但它根本没有帮助。

此外,当我打开此 Scenview 时,控制台上会出现此错误消息。“[SceneKit] 错误:_C3DUnProjectPoints 中出现错误”也许这条消息与 hitTest 故障有关?

<小时/>

已更新

此代码用于构建广告牌 SCNGeometry 和 SCNNode

override func initializeGeometry() -> SCNGeometry {
let geometry = SCNPlane(width: width, height: height)
let material = geometry.materials.first
material?.diffuse.contents = initializeTexture()
material?.writesToDepthBuffer = false
material?.readsFromDepthBuffer = false
return geometry
}

//====构建节点

node = SCNNode()
node.geometry = initializeGeometry()
node.categoryBitMask = MyConstraints.targetNodeHitTestCategoryBitMask
node.constraints = [SCNBillboardConstraint()]

最佳答案

您正在检索 annotationsDisplayView 中的点击坐标,然后将这些坐标传递给 sceneView 进行点击测试查找。除非这些 View 完全重叠,否则您会得到不匹配的结果。

我想你想要

    let location = gestureRecognize.location(in: sceneView)

相反。

我很好奇 HitTest 是否会使用广告牌的旋转版本。我确认确实如此。这是一个工作 (Mac) 示例。

SCNView子类中:

override func mouseDown(with theEvent: NSEvent) {
/* Called when a mouse click occurs */

// check what nodes are clicked
let p = self.convert(theEvent.locationInWindow, from: nil)
let hitResults = self.hitTest(p, options: [:])
// check that we clicked on at least one object
if hitResults.count > 0 {
Swift.print("hit me")
}
for result in hitResults {
Swift.print(result.node.name)

// get its material
let material = result.node.geometry!.firstMaterial!

// highlight it
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5

// on completion - unhighlight
SCNTransaction.completionBlock = {
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5

material.emission.contents = NSColor.black

SCNTransaction.commit()
}

material.emission.contents = NSColor.yellow

SCNTransaction.commit()
}

super.mouseDown(with: theEvent)
}

在 View Controller 中:

override func awakeFromNib(){
super.awakeFromNib()

// create a new scene
let scene = SCNScene()

let side = CGFloat(2.0)
let quad1 = SCNNode.init(geometry: SCNPlane(width: side, height: side))
quad1.name = "green"
quad1.geometry?.firstMaterial?.diffuse.contents = NSColor.green

let quad2 = SCNNode.init(geometry: SCNPlane(width: side, height: side))
quad2.name = "red"
quad2.geometry?.firstMaterial?.diffuse.contents = NSColor.red

let quad3 = SCNNode.init(geometry: SCNPlane(width: side, height: side))
quad3.name = "blue"
quad3.geometry?.firstMaterial?.diffuse.contents = NSColor.blue

scene.rootNode.addChildNode(quad1)
scene.rootNode.addChildNode(quad2)
scene.rootNode.addChildNode(quad3)

let rotation = CGFloat(M_PI_2) * 0.9
quad1.position.y = side/2
quad1.eulerAngles.y = rotation

quad2.position.x = side/2
quad2.eulerAngles.x = rotation

// comment out these constraints to verify that they matter
quad1.constraints = [SCNBillboardConstraint()]
quad2.constraints = [SCNBillboardConstraint()]

// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)

// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)

// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.color = NSColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)

// set the scene to the view
self.gameView!.scene = scene

// allows the user to manipulate the camera
self.gameView!.allowsCameraControl = true

// show statistics such as fps and timing information
self.gameView!.showsStatistics = true

// configure the view
self.gameView!.backgroundColor = NSColor.black
}

关于ios - SceneKit: HitTest 不适用于广告牌四边形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39930878/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com