I have to set the physics physique of a node. When I’ve a customized pivot however with out scales or rotation, I can merely remodel the form by the inverse of the pivot, like this:
let boxGeo = SCNBox(width: 5, peak: 5, size: 1, chamferRadius: 0)
let field = SCNNode(geometry: boxGeo)
rootNode.addChildNode(field)
// i've a customized pivot right here:
field.pivot = SCNMatrix4MakeTranslation(1, 1, 1)
// i can merely remodel the form by inverse of pivot:
let boxPhysicsShape = SCNPhysicsShape(geometry: field.geometry!)
.reworked(by: SCNMatrix4Invert(field.pivot))
field.physicsBody = SCNPhysicsBody(kind: .static, form: boxPhysicsShape)
Notice that reworked(by:)
is a helper operate that I present beneath:
public extension SCNPhysicsShape {
func reworked(by remodel: SCNMatrix4) -> SCNPhysicsShape {
return SCNPhysicsShape(
shapes: [self],
transforms: [NSValue(scnMatrix4: transform)])
}
func translated(by translation: SCNVector3) -> SCNPhysicsShape {
let remodel = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
return reworked(by: remodel)
}
func scaled(by scale: SCNVector3) -> SCNPhysicsShape {
let remodel = SCNMatrix4MakeScale(scale.x, scale.y, scale.z)
return reworked(by: remodel)
}
func rotated(by rotation: SCNVector4) -> SCNPhysicsShape {
let remodel = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
return reworked(by: remodel)
}
}
This works positive. Nevertheless, when the node is scaled, this would possibly not work anymore:
// ...
field.scale = SCNVector3Make(1.5, 1.5, 1.5)
field.pivot = SCNMatrix4MakeTranslation(1, 1, 1)
// ...
let boxPhysicsShape = SCNPhysicsShape(geometry: field.geometry!)
.scaled(by: field.scale)
.reworked(by: SCNMatrix4Invert(field.pivot))
In the event you activate the showPhysicsShapes
debug possibility, the physics form is misaligned.
Much like scale, when there’s rotation concerned, I can not align the physics form both.
Here is a minimal repro code you may mess around:
class My3DScene: SCNScene {
override init() {
tremendous.init()
let digital camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.digital camera = digital camera
cameraNode.place = SCNVector3(x: 0, y: 0, z: 50)
rootNode.addChildNode(cameraNode)
let boxGeo = SCNBox(width: 5, peak: 5, size: 1, chamferRadius: 0)
boxGeo.firstMaterial?.diffuse.contents = UIColor.crimson
let field = SCNNode(geometry: boxGeo)
field.scale = SCNVector3Make(1.5, 1.5, 1.5)
field.eulerAngles = SCNVector3Make(1, 2, 3)
field.pivot = SCNMatrix4MakeTranslation(1, 1, 1)
rootNode.addChildNode(field)
let boxPhysicsShape = SCNPhysicsShape(geometry: field.geometry!)
// no have to rotate, form is rotated by node robotically
.scaled(by: field.scale)
.reworked(by: SCNMatrix4Invert(field.pivot))
field.physicsBody = SCNPhysicsBody(kind: .static, form: boxPhysicsShape)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been carried out")
}
}
class GameViewController: UIViewController {
override func viewDidLoad() {
tremendous.viewDidLoad()
let scnView = SCNView(body: self.view.body)
scnView.debugOptions = .showPhysicsShapes
self.view.addSubview(scnView)
let scene = My3DScene()
scnView.current(scene, with: .fade(withDuration: 1), incomingPointOfView: nil)
}
}
public extension SCNPhysicsShape {
func reworked(by remodel: SCNMatrix4) -> SCNPhysicsShape {
return SCNPhysicsShape(
shapes: [self],
transforms: [NSValue(scnMatrix4: transform)])
}
func translated(by translation: SCNVector3) -> SCNPhysicsShape {
let remodel = SCNMatrix4MakeTranslation(translation.x, translation.y, translation.z)
return reworked(by: remodel)
}
func scaled(by scale: SCNVector3) -> SCNPhysicsShape {
let remodel = SCNMatrix4MakeScale(scale.x, scale.y, scale.z)
return reworked(by: remodel)
}
func rotated(by rotation: SCNVector4) -> SCNPhysicsShape {
let remodel = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
return reworked(by: remodel)
}
}