如何在scn节点内的不同材料上进行碰撞检测

时间:2017-09-13 03:58:52

标签: collision scenekit detection material

我试图在scn节点内的不同材料之间进行碰撞检测。我有一个立方体,有6种不同的材料/颜色,球在立方体上。我想检测相同和不同颜色的碰撞,但不知道如何对每种材料应用不同的类别。

import UIKit
import SceneKit

class GameViewController: UIViewController, SCNPhysicsContactDelegate {

我可以创建类别以便稍后分配到多维数据集的不同侧吗?

let ballCategory = 0
let cubeCategory = 1
let ballGreen = 2
let ballRed = 3
let ballBlue = 4
let ballYellow = 5
let ballPurple = 6
let ballOrange = 7
let cubeGreen = 8
let cubeRed = 9
let cubeBlue = 10
let cubeYellow = 11
let cubePurple = 12
let cubeOrange = 13

设置内容

var scnView: SCNView!
var scnScene = SCNScene()
var cameraNode: SCNNode!
var cubeNode = SCNNode()
var ball = SCNNode()

var randomColor: UIColor?

var timer = Timer()

override func viewDidLoad() {
    super.viewDidLoad()

    scnScene.physicsWorld.contactDelegate = self

    scnView = self.view as? SCNView

        view.scene = scnScene
        view.isPlaying = true

    }

    setupView()
    setupScene()
    setupCamera()
    spawnCube()

}

物理世界会不会开始接触工作?

func physicsWorld(world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
            print("Physics called")

    if (contact.nodeA == cubeNode || contact.nodeA == ball) && (contact.nodeB == cubeNode || contact.nodeB == ball) {

        print("contact")

    }

    if (contact.nodeA.physicsBody!.categoryBitMask == 2 && contact.nodeB.physicsBody!.categoryBitMask == 8) || (contact.nodeB.physicsBody!.categoryBitMask == 2 && contact.nodeA.physicsBody!.categoryBitMask == 8)  {

        print("green contact")

    }

    if (contact.nodeA.physicsBody!.categoryBitMask == 3 && contact.nodeB.physicsBody!.categoryBitMask == 9) || (contact.nodeB.physicsBody!.categoryBitMask == 3 && contact.nodeA.physicsBody!.categoryBitMask == 9)  {

        print("green contact")

    }

    if (contact.nodeA.physicsBody!.categoryBitMask == 4 && contact.nodeB.physicsBody!.categoryBitMask == 10) || (contact.nodeB.physicsBody!.categoryBitMask == 4 && contact.nodeA.physicsBody!.categoryBitMask == 10)  {

        print("green contact")

    }

    if (contact.nodeA.physicsBody!.categoryBitMask == 5 && contact.nodeB.physicsBody!.categoryBitMask == 11) || (contact.nodeB.physicsBody!.categoryBitMask == 5 && contact.nodeA.physicsBody!.categoryBitMask == 11)  {

        print("green contact")

    }

    if (contact.nodeA.physicsBody!.categoryBitMask == 6 && contact.nodeB.physicsBody!.categoryBitMask == 12) || (contact.nodeB.physicsBody!.categoryBitMask == 6 && contact.nodeA.physicsBody!.categoryBitMask == 12)  {

        print("green contact")

    }

    if (contact.nodeA.physicsBody!.categoryBitMask == 7 && contact.nodeB.physicsBody!.categoryBitMask == 13) || (contact.nodeB.physicsBody!.categoryBitMask == 7 && contact.nodeA.physicsBody!.categoryBitMask == 13)  {

        print("green contact")

    }

}

func setupView() {
    scnView = self.view as! SCNView
    scnView.showsStatistics = false
    scnView.allowsCameraControl = false
    scnView.autoenablesDefaultLighting = true

}

func setupScene() {
    scnScene = SCNScene()
    scnView.scene = scnScene
    scnScene.background.contents = UIColor.black
}

func setupCamera() {

    cameraNode = SCNNode()

    cameraNode.camera = SCNCamera()
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
    scnScene.rootNode.addChildNode(cameraNode)

}

多维数据集设置,当我尝试将类别添加到不同的边/材料时,我收到错误

func spawnCube() {

    var geometry:SCNGeometry

    geometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0.05)

    cubeNode = SCNNode(geometry: geometry)

    let greenMaterial = SCNMaterial()
    greenMaterial.diffuse.contents = UIColor.green
    greenMaterial.locksAmbientWithDiffuse = true

    let redMaterial = SCNMaterial()
    redMaterial.diffuse.contents = UIColor.red
    redMaterial.locksAmbientWithDiffuse = true

    let blueMaterial  = SCNMaterial()
    blueMaterial.diffuse.contents = UIColor.blue
    blueMaterial.locksAmbientWithDiffuse = true

    let yellowMaterial = SCNMaterial()
    yellowMaterial.diffuse.contents = UIColor.yellow
    yellowMaterial.locksAmbientWithDiffuse = true

    let purpleMaterial = SCNMaterial()
    purpleMaterial.diffuse.contents = UIColor.purple
    purpleMaterial.locksAmbientWithDiffuse = true

    let orangeMaterial = SCNMaterial()
    orangeMaterial.diffuse.contents = UIColor.orange
    orangeMaterial.locksAmbientWithDiffuse   = true

    geometry.materials = [greenMaterial,  redMaterial,    blueMaterial,
                          yellowMaterial, purpleMaterial, orangeMaterial]

    cubeNode.physicsBody?.mass = 10000
    cubeNode.physicsBody?.restitution = 0
    cubeNode.physicsBody?.damping = 0
    cubeNode.physicsBody = SCNPhysicsBody.kinematic()
    cubeNode.physicsBody?.categoryBitMask = Int(cubeCategory)
    cubeNode.physicsBody?.contactTestBitMask = Int(ballCategory)
    cubeNode.physicsBody?.isAffectedByGravity = false

    cubeNode.position = SCNVector3(x: 0, y: 0, z: 0)

    scnScene.rootNode.addChildNode(cubeNode)
}

球设置,当我尝试为不同的球颜色添加不同的类别时,我也遇到错误

func spawnBall() {

    var geometry:SCNGeometry

    geometry = SCNSphere(radius: 0.25)

    let ball = SCNNode(geometry: geometry)

    let randomNumberForColor = Int(arc4random_uniform(6))

    if randomNumberForColor == 1 {
        randomColor = UIColor.green
    }
    if randomNumberForColor == 2 {
        randomColor = UIColor.red
    }
    if randomNumberForColor == 3 {
        randomColor = UIColor.blue
    }
    if randomNumberForColor == 4 {
        randomColor = UIColor.yellow
    }
    if randomNumberForColor == 5 {
        randomColor = UIColor.purple
    }
    if randomNumberForColor == 6 {
        randomColor = UIColor.orange
    }
    if randomNumberForColor == nil {
        randomColor = UIColor.green
    }

    let greenMaterial = SCNMaterial()
    greenMaterial.diffuse.contents = randomColor
    greenMaterial.locksAmbientWithDiffuse = true;

    geometry.materials = [greenMaterial]

    ball.physicsBody?.mass = 0.00001
    ball.physicsBody?.restitution = 1
    ball.physicsBody?.damping = 0
    ball.physicsBody = SCNPhysicsBody.dynamic()
    ball.physicsBody?.categoryBitMask = Int(ballCategory)
    ball.physicsBody?.contactTestBitMask = Int(cubeCategory)
    ball.physicsBody?.isAffectedByGravity = false

    randomX()
    randomY()
    randomZ()

    ball.position = SCNVector3(x: Float(randomNumX!), y: Float(randomNumY!), z: Float(randomNumZ!))

    scnScene.rootNode.addChildNode(ball)

    let force = SCNVector3(x: Float(-randomNumX!)/2, y: Float(-randomNumY!)/2, z: Float(-randomNumZ!)/2)

    ball.physicsBody?.applyForce(force, at: cubeNode.position, asImpulse: true)

}

func randomX() {

    randomNumX = Int(arc4random_uniform(10)) - 5

}

func randomY() {

    randomNumY = Int(arc4random_uniform(20)) - 10

}

func randomZ() {

    randomNumZ = Int(arc4random_uniform(10)) - 5

}

}

也许有一种方法可以简化这种方法,只是用匹配颜色的限定符检测球和立方体碰撞?

谢谢!

1 个答案:

答案 0 :(得分:0)

SCNBox类根据需要自动创建SCNGeometryElementobjects以处理材料数量。在您的情况下,您将向geometry.materials添加6种不同的材质,因此您自动拥有6种不同的GeometryElements,每个方块的一侧都有一个。

从SCNPhysicsContact中,您可以获得两个物理实体之间的contact point

然后,您可以执行Hit Test,这将为您提供Hit Test Result的数组。在这种情况下,数组将包含2个元素,意味着2个结果,一个用于立方体,一个用于球。

浏览这两个元素并确定哪个是多维数据集(通过获取结果的'节点'属性来确定节点的名称是' cube&# 39;或者' ball'当然,您需要在创建节点时设置节点的名称属性。)

现在您知道哪个是多维数据集的结果,获取结果的Geometry Index属性。使用该索引获取被球碰撞的面部颜色。

几何元素将与材质数组中的材质具有相同的顺序,例如,如果您获得了几何元素索引0,那么这是材质数组中的第一个材质,依此类推。