2016-01-29 38 views
0

我試圖讓這些「奶牛」以某種方式充當骰子,但無論出於何種原因,他們的物理開始有點瘋狂。我一直試圖找出這個問題約10個小時,只是不能。我正在關注另一個關於SceneKit的教程,並且他製作的球沒有這樣做,所以他們可能會在我使用的模型中出現問題?Swift SceneKit物理瘋狂

以下是對我的應用程序在做視頻:

Youtube Video

這裏是我的視圖控制器代碼:

import UIKit 
import SceneKit 

class RootViewController: UIViewController, SCNSceneRendererDelegate, SCNPhysicsContactDelegate { 

let BALL_RADIUS = CGFloat(15) 

var _scene:SCNScene! 
var _cameraNode:SCNNode! 
var _cameraHandle:SCNNode! 
var _cameraOrientation:SCNNode! 
var _spotLightNode:SCNNode! 
var _spotLightParentNode:SCNNode! 
var _floorNode:SCNNode! 
var _rollingBall:SCNNode! 

var _cowNode:SCNNode! 

var _ambientLightNode:SCNNode! 

var _cameraHandleTranforms = [SCNMatrix4](count:10, repeatedValue:SCNMatrix4(m11: 0.0, m12: 0.0, m13: 0.0, m14: 0.0, m21: 0.0, m22: 0.0, m23: 0.0, m24: 0.0, m31: 0.0, m32: 0.0, m33: 0.0, m34: 0.0, m41: 0.0, m42: 0.0, m43: 0.0, m44: 0.0)) 


override func viewDidLoad() { 
    super.viewDidLoad() 
    setup() 

} 

@IBAction func dropCow(sender: UIButton) { 
    setUpCows() 
} 
func setup() { 
    let sceneView = view as! SCNView 



    sceneView.backgroundColor = UIColor.blackColor() 

    setupScene() 


    sceneView.scene = _scene 

//  sceneView.scene?.physicsWorld.speed = CGFloat(2.0) 
//  
//  sceneView.scene?.physicsWorld.gravity = SCNVector3Make(0, -70, 0) 

//  let bridge = PhysicsWorldBridge() 
//  bridge.physicsWorldSpeed(sceneView.scene, withSpeed: 2.0) 
//  bridge.physicsGravity(sceneView.scene, withGravity: SCNVector3Make(0, -70, 0)) 

    sceneView.delegate = self 

    sceneView.jitteringEnabled = true 

    sceneView.pointOfView = _cameraNode 

    sceneView.showsStatistics = true 
} 


func setupScene() { 
    _scene = SCNScene() 
    setupEnviroment() 
    setupInitial() 
} 

func setupEnviroment() { 
    //create main camera 
    _cameraNode = SCNNode() 
    _cameraNode.position = SCNVector3Make(0, 0, 120) 

    //create a node to manipulate the camera orientation 
    _cameraHandle = SCNNode() 
    _cameraHandle.position = SCNVector3Make(0, 60, 0) 

    _cameraOrientation = SCNNode() 

    _scene.rootNode.addChildNode(_cameraHandle) 
    _cameraHandle.addChildNode(_cameraOrientation) 
    _cameraOrientation.addChildNode(_cameraNode) 

    _cameraNode.camera = SCNCamera() 
    _cameraNode.camera!.zFar = 400 

    if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Phone { 
     _cameraNode.camera!.yFov = 55 
    } else { 
     _cameraNode.camera!.xFov = 75 
    } 

    _cameraHandleTranforms.insert(_cameraNode.transform, atIndex: 0) 

    let position = SCNVector3Make(200, 0, 1000) 

    _cameraNode.position = SCNVector3Make(200, -20, position.z+150) 
    _cameraNode.eulerAngles = SCNVector3Make(CFloat(-M_PI_2)*0.06, 0, 0) 

    //add an ambient light 
    _ambientLightNode = SCNNode() 
    _ambientLightNode.light = SCNLight() 

    _ambientLightNode.light!.type = SCNLightTypeAmbient 
    _ambientLightNode.light!.color = UIColor(white: 0.3, alpha: 1.0) 
    _scene.rootNode.addChildNode(_ambientLightNode) 

    //add a spot light to the scene 
    _spotLightParentNode = SCNNode() 
    _spotLightParentNode.position = SCNVector3Make(0, 90, 20) 

    _spotLightNode = SCNNode() 
    _spotLightNode.rotation = SCNVector4Make(1, 0, 0, CFloat(-M_PI_4)) 
    _spotLightNode.light = SCNLight() 
    _spotLightNode.light!.type = SCNLightTypeSpot 
    _spotLightNode.light!.color = UIColor(white: 1.0, alpha: 1.0) 
    _spotLightNode.light!.castsShadow = true 
    _spotLightNode.light!.shadowColor = UIColor(white: 0, alpha: 0.5) 
    _spotLightNode.light!.zNear = 30 
    _spotLightNode.light!.zFar = 800 
    _spotLightNode.light!.shadowRadius = 1.0 
    _spotLightNode.light!.spotInnerAngle = 15 
    _spotLightNode.light!.spotOuterAngle = 70 

    _cameraNode.addChildNode(_spotLightParentNode) 

    print(_cameraNode.position) 
    _spotLightParentNode.addChildNode(_spotLightNode) 


    //floor 
    let floor = SCNFloor() 
    floor.reflectionFalloffEnd = 0 
    floor.reflectivity = 0 

    _floorNode = SCNNode() 
    _floorNode.geometry = floor 
    _floorNode.geometry!.firstMaterial!.diffuse.contents = "art.scnassets/textures/grass.jpg" 
    _floorNode.geometry!.firstMaterial!.locksAmbientWithDiffuse = true 
    _floorNode.geometry!.firstMaterial!.diffuse.wrapS = SCNWrapMode.Repeat 
    _floorNode.geometry!.firstMaterial!.diffuse.wrapT = SCNWrapMode.Repeat 
    _floorNode.geometry!.firstMaterial!.diffuse.mipFilter = SCNFilterMode.Linear 

    _floorNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: nil) 
    _floorNode.physicsBody!.restitution = 1.0 

    _scene.rootNode.addChildNode(_floorNode) 
} 

func setUpCows() { 
    let cow = SCNScene(named: "art.scnassets/cow.scn")! 

    _cowNode = cow.rootNode.childNodeWithName("scene", recursively: true) 
    _cowNode?.scale = SCNVector3Make(20, 20, 20) 

    //print(cowNode) 

    let cowShape = SCNPhysicsShape(node: _cowNode!, options: nil) 
    let cowBody = SCNPhysicsBody(type: .Dynamic, shape: cowShape) 
    _cowNode?.physicsBody = cowBody 

    _cowNode?.position = SCNVector3(200.0, 0.0, 200) 

    let position = SCNVector3Make(200, 0, 1000) 
    _cowNode.position = position 
    _cowNode.position.y += CFloat(20) 


    let gravityField = SCNPhysicsField.dragField() 
    gravityField.strength = -1.0 
    _cowNode.physicsBody!.restitution = 0.9 
    _cowNode.physicsBody!.angularVelocity = SCNVector4(x: 5, y: 1, z: 1, w: 1) 
    _cowNode?.physicsField = gravityField 

    //print(cowNode) 

    _scene.rootNode.addChildNode(_cowNode!) 

} 

func setupInitial() { 
    //initial dark lighting 
    _ambientLightNode.light!.color = UIColor.blackColor() 
    _spotLightNode.light!.color = UIColor.blackColor() 
    _spotLightNode.position = SCNVector3Make(50, 90, -50) 
    _spotLightNode.eulerAngles = SCNVector3Make(CFloat(-M_PI_2)*0.75, CFloat(M_PI_4)*0.5, 0) 

    setUpCows() 

    SCNTransaction.begin() 
    SCNTransaction.setAnimationDuration(1.0) 
    SCNTransaction.setCompletionBlock() { 
     SCNTransaction.begin() 
     SCNTransaction.setAnimationDuration(2.5) 
     self._spotLightNode.light!.color = UIColor(white: 1, alpha: 1) 
     SCNTransaction.commit() 
    } 

    _spotLightNode.light!.color = UIColor(white: 0.001, alpha: 1) 
    SCNTransaction.commit() 

} 

func handleTap() { 
    SCNTransaction.begin() 
    SCNTransaction.setAnimationDuration(1.0) 

    SCNTransaction.setCompletionBlock() { 
    print("done") 
    } 

    _cameraNode.position.z -= 100 

    SCNTransaction.commit() 
} 


override func shouldAutorotate() -> Bool { 
    return true 
} 

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone { 
     return UIInterfaceOrientationMask.AllButUpsideDown 
    } else { 
     return UIInterfaceOrientationMask.All 
    } 
} 


override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Release any cached data, images, etc that aren't in use. 
} 

} 

任何幫助,將不勝感激謝謝

+0

你想讓你的奶牛跌倒在地板上嗎? – smdsgn

+0

我問,因爲你給你的奶牛設置了重力場。所以我想確定一下。 – smdsgn

+0

是的,他們應該像扔骰子一樣行事。我主要關心的是他們在做軌道的事情,並在地板/飛機下面,只是瘋狂地跳躍 – KyleMassacre

回答

2

因爲這個重力場,你的奶牛有點瘋狂。

let gravityField = SCNPhysicsField.dragField() 
gravityField.strength = -1.0 
_cowNode.physicsBody!.restitution = 0.9 
_cowNode.physicsBody!.angularVelocity = SCNVector4(x: 5, y: 1, z: 1, w: 1) 
_cowNode?.physicsField = gravityField 

如果你希望你的奶牛下跌,反彈如切成小方塊,你需要刪除這個重力場,並配置新的物理環境。

設置你的世界的比重:

sceneView.scene?.physicsWorld.gravity = SCNVector3Make(0, -400, 0) 

而且適用於一些物理到您的奶牛:

_cowNode.physicsBody!.friction = 0.3 
_cowNode.physicsBody!.restitution = 0.7 
_cowNode.physicsBody!.mass = 0.5 
_cowNode.physicsBody!.angularVelocity = SCNVector4(x: 5, y: 1, z: 1, w: 1) 

這是你的代碼的工作示例(我用的立方體取代了牛):

import UIKit 
import SceneKit 

class ViewController: UIViewController, SCNSceneRendererDelegate, SCNPhysicsContactDelegate { 

    let BALL_RADIUS = CGFloat(15) 

    var _scene:SCNScene! 
    var _cameraNode:SCNNode! 
    var _cameraHandle:SCNNode! 
    var _cameraOrientation:SCNNode! 
    var _spotLightNode:SCNNode! 
    var _spotLightParentNode:SCNNode! 
    var _floorNode:SCNNode! 
    var _rollingBall:SCNNode! 

    var _cowNode:SCNNode! 

    var _ambientLightNode:SCNNode! 

    var _cameraHandleTranforms = [SCNMatrix4](count:10, repeatedValue:SCNMatrix4(m11: 0.0, m12: 0.0, m13: 0.0, m14: 0.0, m21: 0.0, m22: 0.0, m23: 0.0, m24: 0.0, m31: 0.0, m32: 0.0, m33: 0.0, m34: 0.0, m41: 0.0, m42: 0.0, m43: 0.0, m44: 0.0)) 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     setup() 

    } 

    @IBAction func dropCow(sender: UIButton) { 
     setUpCows() 
    } 
    func setup() { 
     let sceneView = view as! SCNView 



     sceneView.backgroundColor = UIColor.blackColor() 

     setupScene() 


     sceneView.scene = _scene 

     //sceneView.scene?.physicsWorld.speed = CGFloat(2.0) 

     sceneView.scene?.physicsWorld.gravity = SCNVector3Make(0, -400, 0) 

     //  let bridge = PhysicsWorldBridge() 
     //  bridge.physicsWorldSpeed(sceneView.scene, withSpeed: 2.0) 
     //  bridge.physicsGravity(sceneView.scene, withGravity: SCNVector3Make(0, -70, 0)) 

     sceneView.delegate = self 

     sceneView.jitteringEnabled = true 

     sceneView.pointOfView = _cameraNode 

     sceneView.showsStatistics = true 
    } 


    func setupScene() { 
     _scene = SCNScene() 
     setupEnviroment() 
     setupInitial() 
    } 

    func setupEnviroment() { 
     //create main camera 
     _cameraNode = SCNNode() 
     _cameraNode.position = SCNVector3Make(0, 0, 120) 

     //create a node to manipulate the camera orientation 
     _cameraHandle = SCNNode() 
     _cameraHandle.position = SCNVector3Make(0, 60, 0) 

     _cameraOrientation = SCNNode() 

     _scene.rootNode.addChildNode(_cameraHandle) 
     _cameraHandle.addChildNode(_cameraOrientation) 
     _cameraOrientation.addChildNode(_cameraNode) 

     _cameraNode.camera = SCNCamera() 
     _cameraNode.camera!.zFar = 400 

     if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Phone { 
      _cameraNode.camera!.yFov = 55 
     } else { 
      _cameraNode.camera!.xFov = 75 
     } 

     _cameraHandleTranforms.insert(_cameraNode.transform, atIndex: 0) 

     let position = SCNVector3Make(200, 0, 1000) 

     _cameraNode.position = SCNVector3Make(200, -20, position.z+150) 
     _cameraNode.eulerAngles = SCNVector3Make(CFloat(-M_PI_2)*0.06, 0, 0) 

     //add an ambient light 
     _ambientLightNode = SCNNode() 
     _ambientLightNode.light = SCNLight() 

     _ambientLightNode.light!.type = SCNLightTypeAmbient 
     _ambientLightNode.light!.color = UIColor(white: 0.3, alpha: 1.0) 
     _scene.rootNode.addChildNode(_ambientLightNode) 

     //add a spot light to the scene 
     _spotLightParentNode = SCNNode() 
     _spotLightParentNode.position = SCNVector3Make(0, 90, 20) 

     _spotLightNode = SCNNode() 
     _spotLightNode.rotation = SCNVector4Make(1, 0, 0, CFloat(-M_PI_4)) 
     _spotLightNode.light = SCNLight() 
     _spotLightNode.light!.type = SCNLightTypeSpot 
     _spotLightNode.light!.color = UIColor(white: 1.0, alpha: 1.0) 
     _spotLightNode.light!.castsShadow = true 
     _spotLightNode.light!.shadowColor = UIColor(white: 0, alpha: 0.5) 
     _spotLightNode.light!.zNear = 30 
     _spotLightNode.light!.zFar = 800 
     _spotLightNode.light!.shadowRadius = 1.0 
     _spotLightNode.light!.spotInnerAngle = 15 
     _spotLightNode.light!.spotOuterAngle = 70 

     _cameraNode.addChildNode(_spotLightParentNode) 

     print(_cameraNode.position) 
     _spotLightParentNode.addChildNode(_spotLightNode) 


     //floor 
     let floor = SCNFloor() 
     floor.reflectionFalloffEnd = 0 
     floor.reflectivity = 0 

     _floorNode = SCNNode() 
     _floorNode.geometry = floor 
     _floorNode.geometry!.firstMaterial!.diffuse.contents = "art.scnassets/textures/grass.jpg" 
     _floorNode.geometry!.firstMaterial!.locksAmbientWithDiffuse = true 
     _floorNode.geometry!.firstMaterial!.diffuse.wrapS = SCNWrapMode.Repeat 
     _floorNode.geometry!.firstMaterial!.diffuse.wrapT = SCNWrapMode.Repeat 
     _floorNode.geometry!.firstMaterial!.diffuse.mipFilter = SCNFilterMode.Linear 

     _floorNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: nil) 
     _floorNode.physicsBody!.restitution = 1.0 

     _scene.rootNode.addChildNode(_floorNode) 
    } 

    func setUpCows() { 

     let box = SCNBox(width: 10, height: 10, length: 10, chamferRadius: 0.0) 
     _cowNode = SCNNode(geometry: box) 

     let cowShape = SCNPhysicsShape(node: _cowNode!, options: nil) 
     let cowBody = SCNPhysicsBody(type: .Dynamic, shape: cowShape) 
     _cowNode?.physicsBody = cowBody 

     _cowNode?.position = SCNVector3(200.0, 0.0, 200) 

     let position = SCNVector3Make(200, 40, 1000) 
     _cowNode.position = position 
     _cowNode.position.y += CFloat(20) 

     _cowNode.physicsBody!.friction = 0.3 
     _cowNode.physicsBody!.restitution = 0.7 
     _cowNode.physicsBody!.mass = 0.5 
     _cowNode.physicsBody!.angularVelocity = SCNVector4(x: 5, y: 1, z: 1, w: 1) 

     //print(cowNode) 

     _scene.rootNode.addChildNode(_cowNode!) 

    } 

    func setupInitial() { 
     //initial dark lighting 
     _ambientLightNode.light!.color = UIColor.blackColor() 
     _spotLightNode.light!.color = UIColor.blackColor() 
     _spotLightNode.position = SCNVector3Make(50, 90, -50) 
     _spotLightNode.eulerAngles = SCNVector3Make(CFloat(-M_PI_2)*0.75, CFloat(M_PI_4)*0.5, 0) 

     //setUpCows() 

     SCNTransaction.begin() 
     SCNTransaction.setAnimationDuration(1.0) 
     SCNTransaction.setCompletionBlock() { 
      SCNTransaction.begin() 
      SCNTransaction.setAnimationDuration(2.5) 
      self._spotLightNode.light!.color = UIColor(white: 1, alpha: 1) 
      SCNTransaction.commit() 
     } 

     _spotLightNode.light!.color = UIColor(white: 0.001, alpha: 1) 
     SCNTransaction.commit() 

    } 

    func handleTap() { 
     SCNTransaction.begin() 
     SCNTransaction.setAnimationDuration(1.0) 

     SCNTransaction.setCompletionBlock() { 
      print("done") 
     } 

     _cameraNode.position.z -= 100 

     SCNTransaction.commit() 
    } 


    override func shouldAutorotate() -> Bool { 
     return true 
    } 

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 
     if UIDevice.currentDevice().userInterfaceIdiom == .Phone { 
      return UIInterfaceOrientationMask.AllButUpsideDown 
     } else { 
      return UIInterfaceOrientationMask.All 
     } 
    } 

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
     /* Called when a touch begins */ 
     setUpCows() 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Release any cached data, images, etc that aren't in use. 
    } 

} 
+0

這是一個不錯的嘗試,併爲箱子工作,所以它必須是我的模型瘋狂的東西,所以我將不得不嘗試和圖那出 – KyleMassacre

+0

很難說,沒有看到你的模型。但按照我的指示,如果仍有問題,那麼您的模型有問題。另外,如果你真的想讓你的奶牛像骰子一樣反應,也許你可以爲它們指定一個立方體物理形狀,但我不確定結果。 – smdsgn