SceneKit SCNCone Physics Bug

Viewed 188

I'm having an issue with the physics of cones and pyramids in SceneKit where the physics body seems to hover above the ground. If I replace it with say a SCNBox then there is no issue. It is more noticeable at smaller scales where the space above the ground is much larger relative to the size of the node. It's almost like there is a fixed offset. It happens whether the cone has the flat side or point facing the floor.

Code and screenshots below (linked), sample created and runs in a newly created Xcode SceneKit project. (Xcode 9, swift 4 but was having the issue in prior version of Xcode and swift 3 as well).

image with geometry image with just physics

import UIKit
import QuartzCore
import SceneKit

var scnView: SCNView!

var scnScene: SCNScene!

var cameraNode: SCNNode!

let universalScale: Float = 1 / 40

enter image description hereclass GameViewController: UIViewController, SCNSceneRendererDelegate {
override func viewDidLoad() {
    super.viewDidLoad()

    setupView()
    setupScene()
    setupCamera()
    spawnFloor()
    spawnShape()
}

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

func setupScene() {
    scnScene = SCNScene()
    scnView.scene = scnScene
}

func setupCamera() {
    cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    cameraNode.position = SCNVector3(x: 0 * universalScale, y: 50 * universalScale, z: 50 * universalScale)
    cameraNode.rotation = SCNVector4Make(1, 0, 0, -Float(Double.pi)/4)
    scnScene.rootNode.addChildNode(cameraNode)
}

func spawnFloor() {
    let floor = SCNFloor()
    floor.reflectivity = 0.5
    let material = floor.firstMaterial
    material?.diffuse.contents = UIColor.gray
    let floorNode = SCNNode(geometry: floor)
    floorNode.physicsBody = SCNPhysicsBody(type: .static, shape: nil)
    scnScene.rootNode.addChildNode(floorNode)
}

var shapeNode: SCNNode?

func spawnShape(){
    let cone = SCNCone(topRadius: 0, bottomRadius:CGFloat(1 * universalScale), height: CGFloat(universalScale * 2))
    let coneShape = SCNPhysicsShape(geometry: cone, options: nil)
    let coneNode = SCNNode(geometry: cone)
    coneNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: coneShape)
    coneNode.position = SCNVector3(0, -coneNode.boundingBox.min.y + 20*universalScale, 0)
    scnScene.rootNode.addChildNode(coneNode)
    shapeNode = coneNode
}

func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
    if shapeNode != nil{
        print(shapeNode!.presentation.position)
        print(shapeNode!.boundingBox.min)
    }
}
}
0 Answers
Related