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)
}
}
}