Search code examples
swiftios11augmented-realityxcode9arkit

ARKit – Ball is not passing through "SCNTorus" hole


I am stuck with an issue on ARKit and I need help. I am making a little demo where I am placing a simple SCNTorus geometry in the scene and I am trying to throw a small ball (SCNSphere) into the torus hole. The problem is that the ball is bouncing in the middle rather than pass through. There is the code for the torus:

let ring = SCNTorus(ringRadius: 0.4, pipeRadius: 0.1)
ring.ringSegmentCount = 100

let ringMaterial = SCNMaterial()
ringMaterial.diffuse.contents = UIImage(named: "art.scnassets/Ball/BeachBallColor.jpg")

ring.materials = [ringMaterial]

let ringNode = SCNNode()
ringNode.position = SCNVector3(x: location.worldTransform.columns.3.x,
                               y: location.worldTransform.columns.3.y + 0.8,
                               z: location.worldTransform.columns.3.z)

ringNode.geometry = ring

let body = SCNPhysicsBody(type: SCNPhysicsBodyType.kinematic,
                               shape: nil)
body.categoryBitMask = CollisionTypes.wall.rawValue
body.collisionBitMask = CollisionTypes.beachball.rawValue
// body.contactTestBitMask = CollisionTypes.beachball.rawValue
body.isAffectedByGravity = false
body.mass = 0.5

ringNode.physicsBody = body

sceneView.scene.rootNode.addChildNode(ringNode)

And for the ball :

let node = SCNNode(geometry: sphere!)
node.renderingOrder = 10

let body = SCNPhysicsBody(type: SCNPhysicsBodyType.dynamic,shape: nil)
body.categoryBitMask = CollisionTypes.beachball.rawValue
body.collisionBitMask = CollisionTypes.solid.rawValue|CollisionTypes.wall.rawValue|CollisionTypes.beachball.rawValue
// body.contactTestBitMask = CollisionTypes.fireball.rawValue|CollisionTypes.wall.rawValue
body.isAffectedByGravity = true
body.mass = 0.5
body.restitution = 0.75
body.damping = 0.1
body.friction = 0.8

node.physicsBody = body

Solution

  • The code you use to create the physicsbody (body type kinametic and shape nil) results in a simplified “convex hull” representation of the geometry. Simply put, the geometry you see is a torus, but the geometry used for the collision detection is not.

    This line of (obj c) code is actually from one of the Apple sample code projects:

    _torus.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeStatic shape:[SCNPhysicsShape shapeWithGeometry:_torus.geometry options: @{SCNPhysicsShapeTypeKey : SCNPhysicsShapeTypeConcavePolyhedron} ] ];
    

    In other words, you need to create a static type body and a shape based on the geometry itself using the SCNPhysicsShapeTypeConcavePolyhedron key value (which only works for static bodies) to end up with a more accurate representation of the torus geometry as the physics body.

    For more details see: https://developer.apple.com/documentation/scenekit/scnphysicsshape