SceneKit physics is not behaving as intended

I have 4 walls, 1 ceiling, 1 floor and a furniture. I am dragging my furniture in the room but it is going through walls. I tried everything I know. Still cannot solved the problem. Contact detection is working. My furniture node is not staying on the floor if I don’t give it furniture.physicsBody!.damping = 1.0 property. Please check the video : https://youtu.be/1iwq7gvTzA4

enum ABC:Int {
    case furni = 1
    case wall = 4
    case floor = 6
}

private func setup() {
    // create the wall geometry
    let wallGeometry = SCNPlane(width: 2000, height: 300)
    wallGeometry.firstMaterial!.diffuse.contents = "Wallpaper1.png"
    wallGeometry.firstMaterial!.isDoubleSided = false
    wallGeometry.firstMaterial!.locksAmbientWithDiffuse = true

    let wallWithBaseboardNode = SCNNode(geometry: wallGeometry)
    wallWithBaseboardNode.position = SCNVector3Make(0, 150, 0)
    wallWithBaseboardNode.physicsBody = .static()
    wallWithBaseboardNode.physicsBody!.restitution = 1.0
    wallWithBaseboardNode.physicsBody!.contactTestBitMask = ABC.furni.rawValue

    //front
    _wallNode = wallWithBaseboardNode.clone()
    _scene.rootNode.addChildNode(_wallNode)

    //left
    _wallNode = wallWithBaseboardNode.clone()
    _wallNode.position = SCNVector3Make(0, 150, 0)
    _wallNode.rotation = SCNVector4Make(0, 1, 0, .pi/2)
    _scene.rootNode.addChildNode(_wallNode)

    //right
    _wallNode = wallWithBaseboardNode.clone()
    _wallNode.position = SCNVector3Make(roomDimensions[0], 150, 0)
    _wallNode.rotation = SCNVector4Make(0, 1, 0, -.pi/2)
    _scene.rootNode.addChildNode(_wallNode)

    //back
    _wallNode = wallWithBaseboardNode.clone()
    _wallNode.position = SCNVector3Make(0, 150, roomDimensions[1])
    _wallNode.rotation = SCNVector4Make(0, 1, 0, .pi/1)
    _scene.rootNode.addChildNode(_wallNode)

    //ceiling
    var ceilingNode = wallWithBaseboardNode.clone()
    ceilingNode = wallWithBaseboardNode.copy() as! SCNNode
    ceilingNode.geometry = (ceilingNode.geometry!.copy() as! SCNGeometry)
    ceilingNode.geometry!.firstMaterial = SCNMaterial()
    ceilingNode.geometry!.firstMaterial!.diffuse.contents = UIColor.white
    ceilingNode.position = SCNVector3Make(0, Float(wallGeometry.height), 0)
    ceilingNode.scale = SCNVector3Make(10, 10, 10)
    ceilingNode.rotation = SCNVector4Make(1, 0, 0, .pi/2)
    _scene.rootNode.addChildNode(ceilingNode)

    //floor
    let floor = SCNFloor()
    floor.reflectionFalloffEnd = 0
    floor.reflectivity = 0

    _floorNode = SCNNode()
    _floorNode.geometry = floor
    _floorNode.geometry!.firstMaterial!.diffuse.contents = "Wood3.jpg"
    _floorNode.geometry!.firstMaterial!.locksAmbientWithDiffuse = true
    _floorNode.geometry!.firstMaterial!.diffuse.wrapS = .repeat
    _floorNode.geometry!.firstMaterial!.diffuse.wrapT = .repeat
    _floorNode.geometry!.firstMaterial!.diffuse.mipFilter = .nearest
    _floorNode.geometry!.firstMaterial!.isDoubleSided = false

    _floorNode.physicsBody = .static()
    _floorNode.physicsBody!.restitution = 1.0

    //_floorNode.physicsBody!.contactTestBitMask = ABC.furni.rawValue

    _scene.rootNode.addChildNode(_floorNode)
}

And this is the code for my furniture node

private func addFurniture() {
    let furnitureScene = SCNScene(named: "a.dae", inDirectory: "assets.scnassets/models/", options: nil)!
    let furniture = furnitureScene.rootNode.childNode(withName: "a", recursively: true)!

    furniture.physicsBody = .dynamic()
    furniture.physicsBody!.restitution = 1.0
    furniture.physicsBody!.damping = 1.0

    furniture.physicsBody!.contactTestBitMask = ABC.wall.rawValue

    _scene.rootNode.addChildNode(furniture)

    scnView.prepare(_scene, shouldAbortBlock: nil)

    _furniture = furniture

    scnView.debugOptions = [.showPhysicsShapes, .showPhysicsFields]
}

1

Answers


  1. mike_t
    0 Votes

    If you want to move the furniture manualy (i.e. not using forces), change the body type to .kinematic

    When you move the node , you can perform contactTest(with:options:) which will return you a list of contacts if you hit the walls. In the renderer(_:willRenderScene:atTime:) you can then fix the position of the furniture to “fix” the wall penetration offset against the wall.

    You can see my solution of a similar problem here:
    https://stackoverflow.com/a/46915698/1389597

    Hope this helps, i’ve spent several days trying to figure this out 🙂

Please signup or login to answer this question.

Signup for an account and start participating in our site today!




Social Signup

You can also login with your Facebook, Twitter or Linkedin account

Log in with Facebook