我正在尝试制作这些" Cows"在某种程度上充当骰子,但无论出于何种原因,他们的物理开始变得疯狂。我一直试图解决这个问题大约10个小时而且不能理解。我正在关注另一个关于SceneKit和他的球的教程,他所做的并不是那样,所以我们使用的模型会出现问题吗?
以下是我的应用程序正在执行的操作的视频:
这是我的视图控制器代码:
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 :(得分: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
如果您希望您的奶牛摔倒并弹跳骰子,您需要移除此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.
}
}