我想用Scene套件创建一个应用来解决Rubix Cube。我有自己的立方体dae文件。接触开始后,我有一个被击中的对象
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)
}
}
如何准确找到多维数据集的哪个面?
答案 0 :(得分:7)
faceIndex
看起来很有希望,但实际上并没有得到你认为有用的东西。由该属性计算的“面”是网格的细分,因此立方体不是六个四边形的集合,它将是十二个三角形。 (或者更多:在某些情况下,即使是平面的立方体也会被曲面细分,每边有多个四边形/两个三角形。如果你使用的是SCNBox
,你可以用widthSegmentCount
来控制它们。)
相反 - 特别是如果您的多维数据集是SCNBox
- 最简单的解决方案可能是利用该类的这种有趣的行为:
您最多可以为每个边框分配六个
SCNMaterial
个实例 - 其materials
属性。SCNBox
类会根据需要自动创建SCNGeometryElement
个对象以处理材料数量。
所以,如果你分配了六种材料,你会得到一面:
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
将有六个几何元素 - 每个材质一个,对应于每一个一个。
现在,您可以使用命中测试找出点击的几何元素:
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)
}
或者,如果您没有突出显示并希望将面部索引用于逻辑,那么可以使用以下内容的开头:
enum CubeFace: Int {
case Front, Right, Back, Left, Top, Bottom
}
// when processing hit test result:
print("hit face: \(CubeFace(rawValue: result.geometryIndex))")
答案 1 :(得分:3)
我们使用此功能根据SCNHitResult
中的localNormal值确定面部匹配。
如果轴的大小为1,则此函数会结束面部被击中。
它假设只有一个且只有一个轴的幅度等于1.否则代码将会中断。它还假设SCNBox几何。
在测试中,这似乎有效(对于SCNBox几何)。唯一的复杂因素是localNormal
值并不总是返回clean 0值。有时它会返回-5.96046448e-08之类的值,因此我们使用round
函数是安全的,以防相同的情况适用于接近1但不完全为1的值。
我们是SceneKit和3D的新手,所以代码可能存在缺陷。如果您发现问题或潜在的优化,请发表评论。
private func getHitFaceFromNormal(normal: SCNVector3) {
if round(normal.x) == -1 {
// Left face hit
} else if round(normal.x) == 1 {
// Right face hit
} else if round(normal.y) == -1 {
// Bottom face hit
} else if round(normal.y) == 1 {
// Top face hit
} else if round(normal.z) == -1 {
// Back face hit
} else if round(normal.z) == 1 {
// Front face hit
} else {
// Error, no face detected
}
}