在 Swift 中识别触碰的立方体的面 - SceneKit [英] Identify face of a cube hit on touches began in Swift - SceneKit
问题描述
我打算用 SceneKit 创建一个应用程序来解决魔方问题.我为立方体制作了自己的 dae
文件.触摸开始时,我有被击中的对象
I'm tying to create an app with SceneKit to solve a Rubik's Cube. I've made my own dae
file for the cube. Upon touches began I have the object that's been hit
func tapGesture(sender: UITapGestureRecognizer){
// check what nodes are tapped
var p = sender.locationInView(sceneView)
var hitResults = sceneView.hitTest(p, options: nil)
if hitResults.count > 0
{
var hitnode = (hitResults.first)!.node
print("\nName of node hit is \(hitnode.name)")
//var indexvalue = hitResults.first?.faceIndex
//print(indexvalue)
}
}
如何准确找到立方体的哪个面被击中?
How can I find exactly which face of the cube is being hit?
推荐答案
faceIndex
看起来很有希望,但实际上不会得到您可能认为有用的东西.该属性计算的面"是网格的细分,因此立方体不会是六个四边形的集合,而是十二个三角形.(或更多:在某些情况下,即使是平面立方体也会被镶嵌成每边超过一个四边形/两个三角形.如果您使用 SCNBox
,您可以使用 widthSegmentCount<控制这些/code> 等)
faceIndex
looks promising, but will not actually get something you're likely to consider useful. The "faces" counted by that property are the tessellation of the mesh, so a cube won't be a collection of six quads, it'll be twelve triangles. (Or more: in some cases, even a flat-sided cube will be tessellated with more than one quad / two triangles per side. If you're using SCNBox
you control these with widthSegmentCount
etc.)
相反——特别是如果你的立方体是一个 SCNBox
——最简单的解决方案可能是利用该类的这个有趣的行为:
Instead — especially if your cube is an SCNBox
— the easiest solution might be to leverage this interesting behavior of that class:
您最多可以将六个 SCNMaterial
实例分配给一个具有 materials
属性的盒子(每侧一个).SCNBox
类根据需要自动创建 SCNGeometryElement
对象来处理材料的数量.
You can assign up to six
SCNMaterial
instances to a box—one for each side—with itsmaterials
property. TheSCNBox
class automatically createsSCNGeometryElement
objects as needed to handle the number of materials.
因此,如果您分配六种材料,则每一面都会得到一种:
So, if you assign six materials, you'll get one for each side:
let front = SCNMaterial()
let right = SCNMaterial()
let back = SCNMaterial()
let left = SCNMaterial()
let top = SCNMaterial()
let bottom = SCNMaterial()
cube.materials = [ front, right, back, left, top, bottom ]
这样做时,您的 SCNBox
将有六个几何元素 — 每种材料一个,每一面对应一个.
And in so doing, your SCNBox
will have six geometry elements — one for each material, which corresponds to one for each side.
现在,您可以使用命中测试来找出被点击的几何元素:
Now, you can use hit testing to find out which geometry element was clicked:
if let result = hitResults.first {
let node = result.node
// Find the material for the clicked element
// (Indices match between the geometryElements and materials arrays)
let material = node.geometry!.materials[result.geometryIndex]
// Do something with that material, for example:
let highlight = CABasicAnimation(keyPath: "diffuse.contents")
highlight.toValue = NSColor.redColor()
highlight.duration = 1.0
highlight.autoreverses = true
highlight.removedOnCompletion = true
material.addAnimation(highlight, forKey: nil)
}
或者,如果您不突出显示并希望使用人脸索引进行逻辑,那么您可以使用以下内容的开头:
Or if you're not highlighting and want to use the face index for logic, here's the beginning of something you could use for that:
enum CubeFace: Int {
case Front, Right, Back, Left, Top, Bottom
}
// when processing hit test result:
print("hit face: \(CubeFace(rawValue: result.geometryIndex))")
这篇关于在 Swift 中识别触碰的立方体的面 - SceneKit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!