SceneKit完全停止模拟从即时运行?

时间:2016-01-28 04:15:29

标签: ios swift macos cocoa scenekit

试图让这个简单的滚球模拟运行。我似乎无法找到一种方法让球在所述瞬间停止滚动,然后将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的方式重置到开始位置?

1 个答案:

答案 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()
    }
}