试图让这个简单的滚球模拟运行。我似乎无法找到一种方法让球在所述瞬间停止滚动,然后将isResting标志更新同样快速地重置到起始位置。在跑步时,如果按下复位按钮,球会回到起始位置,但如果没有完成滚动,它将继续滚动。这是不可取的。
import Cocoa
import SceneKit
class AppController : NSObject {
@IBOutlet weak var _sceneView: SCNView!
@IBOutlet weak var _pushButton: NSButton!
@IBOutlet weak var _resetButton: NSButton!
private let _radius = 25.0
private let _mySphereNode = SCNNode()
override func awakeFromNib() {
// assign empty scene
_sceneView.scene = SCNScene()
// setup the sphere
let mySphere = SCNSphere(radius: CGFloat(_radius))
mySphere.geodesic = true
mySphere.segmentCount = 50
mySphere.firstMaterial!.diffuse.contents = NSColor.purpleColor().CGColor
mySphere.firstMaterial!.specular.contents = NSColor.whiteColor().CGColor
// create node for adding sphere
_mySphereNode.position = SCNVector3(0.0, CGFloat(_radius), 0.0)
_mySphereNode.geometry = mySphere
// add physics
let spherePhysicsBody = SCNPhysicsBody.dynamicBody()
spherePhysicsBody.mass = 0.67 // Kg
spherePhysicsBody.friction = 0.3765
spherePhysicsBody.rollingFriction = 0.2734
spherePhysicsBody.damping = 0.5
_mySphereNode.physicsBody = spherePhysicsBody
// attach the sphere node to the scene's root node
_sceneView.scene!.rootNode.addChildNode(_mySphereNode)
// setup ambient light source
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = NSColor(white: 0.35, alpha: 1.0).CGColor
// add ambient light the scene
_sceneView.scene!.rootNode.addChildNode(ambientLightNode)
// setup onmidirectional light
let omniLightNode = SCNNode()
omniLightNode.light = SCNLight()
omniLightNode.light!.type = SCNLightTypeOmni
omniLightNode.light!.color = NSColor(white: 0.56, alpha: 1.0).CGColor
omniLightNode.position = SCNVector3Make(0.0, 200.0, 0.0)
_sceneView.scene!.rootNode.addChildNode(omniLightNode)
// add plane
let myPlane = SCNPlane(width: 125.0, height: 2000.0)
myPlane.widthSegmentCount = 10
myPlane.heightSegmentCount = 10
myPlane.firstMaterial!.diffuse.contents = NSColor.orangeColor().CGColor
myPlane.firstMaterial!.specular.contents = NSColor.whiteColor().CGColor
let planeNode = SCNNode()
planeNode.geometry = myPlane
// rotote -90.0 degrees about the y-axis, then rot
var rotMat = SCNMatrix4MakeRotation(-3.14/2.0, 0.0, 1.0, 0.0)
rotMat = SCNMatrix4Rotate(rotMat, -3.14/2.0, 1.0, 0.0, 0.0)
planeNode.transform = rotMat
planeNode.position = SCNVector3Make(0.0, 0.0, 0.0)
// add physcis to plane
planeNode.physicsBody = SCNPhysicsBody.staticBody()
// add plane to scene
_sceneView.scene!.rootNode.addChildNode(planeNode)
}
@IBAction func moveBall(sender: AnyObject) {
if _mySphereNode.physicsBody!.isResting == true {
let forceApplied = SCNVector3Make(40.0, 0.0, 0.0)
_mySphereNode.physicsBody!.applyForce(forceApplied, impulse: true)
}
else {
print("Ball not at rest!")
}
}
@IBAction func resetBall(sender: AnyObject) {
_mySphereNode.physicsBody!.resetTransform()
}
}
有没有办法停止SceneKit模拟停止并以一种强制isResting标志更新为true的方式重置到开始位置?
答案 0 :(得分:0)
我发现使节点的几何体和物理体无效,然后重新连接它们。这是代码:
import Cocoa
import SceneKit
class AppController : NSObject {
@IBOutlet weak var _sceneView: SCNView!
@IBOutlet weak var _pushButton: NSButton!
@IBOutlet weak var _resetButton: NSButton!
private let _mySphereNode = SCNNode()
private func setupScene() {
// setup ambient light source
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = NSColor(white: 0.35, alpha: 1.0).CGColor
// add ambient light the scene
_sceneView.scene!.rootNode.addChildNode(ambientLightNode)
// setup onmidirectional light
let omniLightNode = SCNNode()
omniLightNode.light = SCNLight()
omniLightNode.light!.type = SCNLightTypeOmni
omniLightNode.light!.color = NSColor(white: 0.56, alpha: 1.0).CGColor
omniLightNode.position = SCNVector3Make(0.0, 200.0, 0.0)
_sceneView.scene!.rootNode.addChildNode(omniLightNode)
// add plane
let myPlane = SCNPlane(width: 125.0, height: 2000.0)
myPlane.widthSegmentCount = 10
myPlane.heightSegmentCount = 10
myPlane.firstMaterial!.diffuse.contents = NSColor.orangeColor().CGColor
myPlane.firstMaterial!.specular.contents = NSColor.whiteColor().CGColor
let planeNode = SCNNode()
planeNode.geometry = myPlane
// rotote -90.0 degrees about the y-axis, then rot
var rotMat = SCNMatrix4MakeRotation(-3.14/2.0, 0.0, 1.0, 0.0)
rotMat = SCNMatrix4Rotate(rotMat, -3.14/2.0, 1.0, 0.0, 0.0)
planeNode.transform = rotMat
planeNode.position = SCNVector3Make(0.0, 0.0, 0.0)
// add physcis to plane
planeNode.physicsBody = SCNPhysicsBody.staticBody()
// add plane to scene
_sceneView.scene!.rootNode.addChildNode(planeNode)
}
private func setupBall() {
let _radius = 25.0
// setup the sphere
let mySphere = SCNSphere(radius: CGFloat(_radius))
mySphere.geodesic = true
mySphere.segmentCount = 50
mySphere.firstMaterial!.diffuse.contents = NSColor.purpleColor().CGColor
mySphere.firstMaterial!.specular.contents = NSColor.whiteColor().CGColor
_mySphereNode.position = SCNVector3(0.0, CGFloat(_radius), 0.0)
_mySphereNode.geometry = mySphere
// add physics
let spherePhysicsBody = SCNPhysicsBody.dynamicBody()
spherePhysicsBody.mass = 0.67 // Kg
spherePhysicsBody.friction = 0.3765
spherePhysicsBody.rollingFriction = 0.2734
spherePhysicsBody.damping = 0.5
_mySphereNode.physicsBody = spherePhysicsBody
}
private func stopBall() {
_mySphereNode.geometry = nil
_mySphereNode.physicsBody = nil
}
override func awakeFromNib() {
// assign empty scene
_sceneView.scene = SCNScene()
// attach the sphere node to the scene's root node
_sceneView.scene!.rootNode.addChildNode(_mySphereNode)
setupScene()
setupBall()
}
@IBAction func moveBall(sender: AnyObject) {
let forceApplied = SCNVector3Make(40.0, 0.0, 0.0)
if _mySphereNode.physicsBody?.isResting == true {
_mySphereNode.physicsBody!.applyForce(forceApplied, impulse: true)
}
}
@IBAction func resetBall(sender: AnyObject) {
// remove the ball from the sphere node
stopBall()
// reset the ball
setupBall()
}
}