Ok so I have all of the parts. Finally the code runs without a problem but right as I'm in the last step, trying to figure out how to add the child I'm having trouble. I created an overlay scene that is over the original Scene but I can't figure out the last step which is added the node/image to the actually screen because the traditional self.addChild(%^%) doesn't work on the "base" node in my code. Any help. Thanks
Code:
import iAd
import UIKit
import GameKit
import SceneKit
import StoreKit
import SpriteKit
import QuartzCore
import Foundation
import AVFoundation
import AudioToolbox
//============================================================
class GameViewController: UIViewController, ADBannerViewDelegate, SKPhysicsContactDelegate, SKSceneDelegate, SCNSceneRendererDelegate, SCNPhysicsContactDelegate{
//--------------True-False-statments-------------------------------------------------
var stickActive:Bool = false
var OnOffense = Bool()
var OnDefense = Bool()
var HasBall = Bool()
var OnCampusField = Bool()
var UserControlled = Bool()
//--------Offense-------------
var QuaterBack = SCNNode()
var RunningBack = SCNNode()
var WideReceiver1 = SCNNode()
var WideReceiver2 = SCNNode()
var Linemen1 = SCNNode()
var Linemen2 = SCNNode()
var Linemen3 = SCNNode()
//--------Defense-------------
var LineBacker1 = SCNNode()
var LineBacker2 = SCNNode()
var CornerBack1 = SCNNode()
var CornerBack2 = SCNNode()
var DefensiveLinemen1 = SCNNode()
var DefensiveLinemen2 = SCNNode()
var DefensiveLinemen3 = SCNNode()
//-----------------Controller-Buttons/Joystick---------------------------------------------------
let base = SKSpriteNode(imageNamed:"VirtualJoystickBase")
let ball = SKSpriteNode(imageNamed:"VirtualJoyStickHandle")
let ship = SKSpriteNode(imageNamed:"Ship")
let Button1 = SKSpriteNode(imageNamed:"BlackAButton")
let Button2 = SKSpriteNode(imageNamed:"BlackAButton")
let Button3 = SKSpriteNode(imageNamed:"BlackAButton")
let Button4 = SKSpriteNode(imageNamed:"BlackAButton")
//-------------------3D-Fields--------------------------------------------
let FieldScene = SCNScene(named: "art.scnassets/TesingCampusField.dae")!
//-------------------3D-Players--------------------------------------------
let GuyScene = SCNScene(named: "art.scnassets/Guy.dae")!
override func viewDidLoad() {
super.viewDidLoad()
let scnView = self.view as! SCNView
let skScene = scnView.overlaySKScene
scnView.overlaySKScene = skScene
scnView.backgroundColor = UIColor.whiteColor()
scnView.scene = FieldScene
scnView.delegate = self
scnView.allowsCameraControl = true
scnView.showsStatistics = false
let Guy1: SCNNode = GuyScene.rootNode.childNodeWithName("Bob_014", recursively: true)!
FieldScene.rootNode.addChildNode(Guy1)
//----Positioning-the-Base-of-the-Joystick-----------
base.size = CGSize(width: 100, height: 100)
base.anchorPoint = CGPointMake(-3.4, -5.2)
skScene?.self.addChild(base)
//----Positioning-the-Ball/Joystick-----------
ball.size = CGSize(width: 50, height: 50)
ball.position = base.position
//---Setting-Up-Ships-Position/PhysicsBody---------------------
ship.position = CGPointMake(0, 200)
ship.size = CGSize(width: 80, height: 80)
ship.physicsBody?.dynamic = true
ship.physicsBody?.allowsRotation = true
ship.physicsBody?.affectedByGravity = true
ship.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Ship"), size: ship.size)
//----A-Button--Creation -------------------
Button1.size = CGSize(width: 40, height: 40)
Button1.anchorPoint = CGPointMake(-3.4, -5.2)
//----B-Button--Creation -------------------
Button2.size = CGSize(width: 40, height: 40)
Button2.anchorPoint = CGPointMake(-1.2, -5.2)
//----C-Button--Creation -------------------
Button3.size = CGSize(width: 40, height: 40)
Button3.anchorPoint = CGPointMake(-2.2, -6.4)
//----C-Button--Creation -------------------
Button4.size = CGSize(width: 40, height: 40)
Button4.anchorPoint = CGPointMake(-2.2, -3.4)
let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap:")
scnView.addGestureRecognizer(tapGesture)
//--------------------------
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
FieldScene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 5, z: 15)
//-----------------------------------------------
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
FieldScene.rootNode.addChildNode(lightNode)
//-----------------------------------------------
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
FieldScene.rootNode.addChildNode(ambientLightNode)
//----------------------------------------------
}
func GotoMainMenu() {
let scene = MainMenuController()
let sKView = self.view! as! SKView
sKView.ignoresSiblingOrder = true
scene.size = sKView.bounds.size
scene.scaleMode = .AspectFill
let reveal = SKTransition.fadeWithDuration(0.45)
sKView.presentScene(scene, transition: reveal)
}
//====================================================================
override func shouldAutorotate() -> Bool {
return true
}
//====================================================================
override func prefersStatusBarHidden() -> Bool {
return true
}
//====================================================================
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
//====================================================================
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
Related
The memory of app increased after segue to VC with scnView. I've used deinit and set geometry to nil but it didn't help. I saw some tips on stack about using deinit to solve this issue, but it doesn't work for me. Memory increased every time when I back to this ViewController with scnScene SceneKit: too much memory persisting
var ship1: SCNNode!
var ship2: SCNNode!
var ship3: SCNNode!
var ship4: SCNNode!
let cameraNode = SCNNode()
let lightNode = SCNNode()
let ambientLightNode = SCNNode()
class RecordVideoViewControllerWS: UIViewController {
#IBOutlet weak var scnView: SCNView!
override func viewDidLoad() {
super.viewDidLoad()
cameraNode.camera = SCNCamera()
scnScene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
scnView.scene = scnScene
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scnScene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.color = UIColor.darkGray
scnScene.rootNode.addChildNode(ambientLightNode)
ship1 = nodeFromResource(assetName: "shipFolder/test0", extensionName: "scn")
ship2 = nodeFromResource(assetName: "shipFolder/test1", extensionName: "scn")
ship3 = nodeFromResource(assetName: "shipFolder/test2", extensionName: "scn")
ship4 = nodeFromResource(assetName: "shipFolder/test3", extensionName: "scn")
scnScene.rootNode.addChildNode(ship1)
scnScene.rootNode.addChildNode(ship2)
scnScene.rootNode.addChildNode(ship3)
scnScene.rootNode.addChildNode(ship4)
}
override func viewWillDisappear(_ animated: Bool) {
ship1.removeFromParentNode()
ship1.geometry = nil
ship2.removeFromParentNode()
ship2.geometry = nil
ship3.removeFromParentNode()
ship3.geometry = nil
ship4.removeFromParentNode()
ship4.geometry = nil
cameraNode.removeFromParentNode()
cameraNode.geometry = nil
lightNode.removeFromParentNode()
lightNode.geometry = nil
ambientLightNode.removeFromParentNode()
ambientLightNode.geometry = nil
}
deinit {
scnScene.rootNode.cleanup()
}
}
extension SCNNode {
func cleanup() {
for child in childNodes {
child.cleanup()
}
geometry = nil
}
}
I'm using SceneKit and Swift to try and move the camera so it's 'focused' on the selected node. I understand I have the defaultCameraController enabled but I was trying to adjust the camera's position via dolly, rotate and translateInCameraSpaceBy but there was no animated transition - it just jumped to the new position.
Is there anyway for the camera to glide into position like how Google Maps slides/then zooms over to a searched location?
Any help would be greatly appreciated :)
Here's my code:
import UIKit
import SceneKit
class ViewController: UIViewController {
var gameView: SCNView!
var scene: SCNScene!
var cameraNode: SCNNode!
override func viewDidLoad() {
super.viewDidLoad()
// Scene
scene = SCNScene()
// Camera
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(0, 0, 10)
scene.rootNode.addChildNode(cameraNode)
// Light
/*
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light?.type = .omni
lightNode.position = SCNVector3(0, 10, 2)
scene.rootNode.addChildNode(lightNode)
*/
// Stars
//let stars = SCNParticleSystem(named: "starsParticles.scnp", inDirectory: nil)!
//scene.rootNode.addParticleSystem(stars)
// Earth
let earthNode = itemPlate()
earthNode.position = SCNVector3(0, 0, 0)
scene.rootNode.addChildNode(earthNode)
// Create orbiting moonOne
let moonNodeOne = itemPlate()
moonNodeOne.position = SCNVector3(3, 0, 0)
earthNode.addChildNode(moonNodeOne)
// Create orbiting moonOne
let moonNodeTwo = itemPlate()
moonNodeTwo.position = SCNVector3(5, 3, 2)
earthNode.addChildNode(moonNodeTwo)
// Create orbiting moonOne
let moonNodeThree = itemPlate()
moonNodeThree.position = SCNVector3(-4, -3, 5)
earthNode.addChildNode(moonNodeThree)
// Scene formation
gameView = self.view as! SCNView
gameView.scene = scene
gameView.showsStatistics = true
gameView.allowsCameraControl = true
gameView.autoenablesDefaultLighting = true
gameView.defaultCameraController.interactionMode = .fly
gameView.defaultCameraController.inertiaEnabled = true
gameView.defaultCameraController.maximumVerticalAngle = 89
gameView.defaultCameraController.minimumVerticalAngle = -89
scene.background.contents = UIImage(named: "orangeBg.jpg")
}
override var prefersStatusBarHidden: Bool {
return true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in: gameView)
let hitList = gameView.hitTest(location, options: nil)
if let hitObject = hitList.first {
let node = hitObject.node
// Update camera position
//gameView.defaultCameraController.translateInCameraSpaceBy(x: node.position.x, y: node.position.y, z: node.position.z + 5)
let onScreenPoint:CGPoint = CGPoint(x: 1.0, y: 1.0)
let viewport:CGSize = CGSize(width: 50, height: 50)
gameView.defaultCameraController.dolly(by: 1.0, onScreenPoint: onScreenPoint, viewport: viewport)
//let newCameraPosition = SCNVector3Make(node.position.x, node.position.y, node.position.z + 10)
print("NODE_HIT_OBJECT_COORDS: \(node.position.x), \(node.position.y) \(node.position.y)")
//let moveToAction = SCNAction.move(by: newCameraPosition, duration: 1.0)
}
}
}
You can implement in your code a methodology like this (sorry, I used macOS project instead iOS, but it's almost the same):
func handleClick(_ gestureRecognizer: NSGestureRecognizer) {
let scnView = self.view as! SCNView
let p = gestureRecognizer.location(in: scnView)
let hitResults = scnView.hitTest(p, options: [:])
if hitResults.count > 0 {
let result = hitResults[0]
let nodePosition = result.node.position.z
var matrix = matrix_identity_float4x4
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.5 // duration in seconds
matrix.columns.3.z = Float(nodePosition + 5.0)
scnView.pointOfView?.position.z = CGFloat(matrix.columns.3.z)
SCNTransaction.commit()
}
}
Or, as a second logical option, you can use SceneKit's constraints:
func handleClick(_ gestureRecognizer: NSGestureRecognizer) {
let scnView = self.view as! SCNView
let p = gestureRecognizer.location(in: scnView)
let hitResults = scnView.hitTest(p, options: [:])
if hitResults.count > 0 {
let result = hitResults[0]
let nodePosition = result.node
let constraint1 = SCNLookAtConstraint(target: nodePosition)
let constraint2 = SCNDistanceConstraint(target: nodePosition)
constraint2.minimumDistance = 5
constraint2.maximumDistance = 9
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.5
scnView.pointOfView?.constraints = [constraint2, constraint1]
SCNTransaction.commit()
}
}
P.S. These two approaches ain't out-of-the-box solutions but rather hints on how to implement what you want to.
Hey I have a 3D game thats not really a game yet. But it has a SceneKit 3D scene and a overlayskscene for the HUD/Controls. the "base" is the base of the joystick and the ball is the handle the problem is that the joystick does not move at all unless the scnView.allowsCameraControl = true. I find that weird. and this is my entire view controller code so nothings left out and if you want you can literally copy and paste it into Xcode to see what I'm talking about. Any help?
Code:
import iAd
import UIKit
import GameKit
import SceneKit
import StoreKit
import SpriteKit
import QuartzCore
import Foundation
import AVFoundation
import AudioToolbox
class GameViewController: UIViewController, ADBannerViewDelegate, SKPhysicsContactDelegate, SKSceneDelegate, SCNSceneRendererDelegate, SCNPhysicsContactDelegate{
var stickActive:Bool = false
let base = SKSpriteNode(imageNamed:"VirtualJoystickBase")
let ball = SKSpriteNode(imageNamed:"VirtualJoyStickHandle")
let ship = SKSpriteNode(imageNamed:"Ship")
var ButtonA = SKSpriteNode(imageNamed:"GreenAButton")
var ButtonO = SKSpriteNode(imageNamed:"CircleButton")
var ButtonY = SKSpriteNode(imageNamed:"YellowYButton")
var ButtonSquare = SKSpriteNode(imageNamed:"BlueSquareButton")
let FieldScene = SCNScene(named: "art.scnassets/TesingCampusField.dae")!
let GuyScene = SCNScene(named: "art.scnassets/Guy.dae")!
let overlayScene = SKScene(size: CGSizeMake(100, 100))
override func viewDidLoad() {
super.viewDidLoad()
let scnView = self.view as! SCNView
scnView.overlaySKScene = overlayScene
scnView.backgroundColor = UIColor.whiteColor()
scnView.scene = FieldScene
scnView.delegate = self
scnView.overlaySKScene!.delegate = self
scnView.overlaySKScene!.anchorPoint = CGPointMake(0, 0)
scnView.overlaySKScene!.physicsWorld.contactDelegate = self
scnView.overlaySKScene!.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
scnView.allowsCameraControl = true
scnView.showsStatistics = false
let Guy1: SCNNode = GuyScene.rootNode.childNodeWithName("Bob_014", recursively: true)!
FieldScene.rootNode.addChildNode(Guy1)
//----Positioning-the-Base-of-the-Joystick-----------
base.size = CGSize(width: 14, height: 24)
base.position = CGPointMake(15, 19)
base.zPosition = 0
overlayScene.addChild(base)
//----Positing-the-Ball/Joystick-----------
ball.size = CGSize(width: 10, height: 17)
ball.position = base.position
ball.zPosition = 1
overlayScene.addChild(ball)
//----A-Button--Creation -------------------
ButtonA.size = CGSize(width: 6, height: 9)
ButtonA.anchorPoint = CGPointMake(-13.3, -0.5)
ButtonA.zPosition = 0
overlayScene.addChild(ButtonA)
//----B-Button--Creation -------------------
ButtonO.size = CGSize(width: 6, height: 9)
ButtonO.anchorPoint = CGPointMake(-14.4, -1.7)
ButtonO.zPosition = 0
overlayScene.addChild(ButtonO)
//----C-Button--Creation -------------------
ButtonSquare.size = CGSize(width: 6, height: 9)
ButtonSquare.anchorPoint = CGPointMake(-12.2, -1.7)
ButtonSquare.zPosition = 0
overlayScene.addChild(ButtonSquare)
//----C-Button--Creation -------------------
ButtonY.size = CGSize(width: 6, height: 9)
ButtonY.anchorPoint = CGPointMake(-13.3, -2.7)
ButtonY.zPosition = 0
overlayScene.addChild(ButtonY)
//---Setting-Up-Ships-Position/PhysicsBody---------------------
ship.position = CGPointMake(0, 100)
ship.size = CGSize(width: 80, height: 80)
ship.physicsBody?.dynamic = true
ship.physicsBody?.allowsRotation = true
ship.physicsBody?.affectedByGravity = true
ship.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Ship"), size: ship.size)
ship.physicsBody!.friction = 0
ship.physicsBody!.restitution = 0
ship.physicsBody!.linearDamping = 0
ship.physicsBody!.angularDamping = 0
//--------------------------
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
GuyScene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 5, z: 15)
//-----------------------------------------------
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
FieldScene.rootNode.addChildNode(lightNode)
//-----------------------------------------------
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
FieldScene.rootNode.addChildNode(ambientLightNode)
//----------------------------------------------
}
func YButtonPressed() {
let YButtonPressed = SKTexture(imageNamed: "YellowYButtonPressed")
let OrignalButtonY = SKTexture(imageNamed:"YellowYButton")
let YButtonPressedAnimation = SKAction.animateWithTextures([YButtonPressed, OrignalButtonY], timePerFrame: 0.2)
let RunYButtonPressedAnimation = SKAction.repeatAction(YButtonPressedAnimation, count: 1)
ButtonY.runAction(RunYButtonPressedAnimation)
}
func OButtonPressed() {
let OButtonPressed = SKTexture(imageNamed: "CircleButtonPressed")
let OrignalButtonO = SKTexture(imageNamed:"CircleButton")
let OButtonPressedAnimation = SKAction.animateWithTextures([OButtonPressed, OrignalButtonO], timePerFrame: 0.2)
let RunOButtonPressedAnimation = SKAction.repeatAction(OButtonPressedAnimation, count: 1)
ButtonO.runAction(RunOButtonPressedAnimation)
}
func SquareButtonPressed() {
let SquareButtonPressed = SKTexture(imageNamed: "BlueSquareButtonPressed")
let OrignalButtonSquare = SKTexture(imageNamed:"BlueSquareButton")
let SquareButtonPressedAnimation = SKAction.animateWithTextures([SquareButtonPressed, OrignalButtonSquare], timePerFrame: 0.2)
let RunSquareButtonPressedAnimation = SKAction.repeatAction(SquareButtonPressedAnimation, count: 1)
ButtonSquare.runAction(RunSquareButtonPressedAnimation)
}
func AButtonPressed() {
let AButtonPressed = SKTexture(imageNamed: "GreenAButtonPressed")
let OrignalButtonA = SKTexture(imageNamed:"GreenAButton")
let AButtonPressedAnimation = SKAction.animateWithTextures([AButtonPressed, OrignalButtonA], timePerFrame: 0.2)
let RunAButtonPressedAnimation = SKAction.repeatAction(AButtonPressedAnimation, count: 1)
ButtonA.runAction(RunAButtonPressedAnimation)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self.overlayScene)
if (CGRectContainsPoint(base.frame, location)) {
print("stickActive = true")
stickActive = true
} else {
print("stickActive = false")
stickActive = false
}
}
for touch: AnyObject in touches {
let location1 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location1) == self.ButtonA {
AButtonPressed()
print("AButtonPressed")
}
}
for touch: AnyObject in touches {
let location2 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location2) == self.ButtonO {
OButtonPressed()
print("OButtonPressed")
}
}
for touch: AnyObject in touches {
let location3 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location3) == self.ButtonY {
YButtonPressed()
print("YButtonPressed")
}
}
for touch: AnyObject in touches {
let location4 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location4) == self.ButtonSquare {
SquareButtonPressed()
print("SquarButtonPressed")
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location) == self.ball {
if (stickActive == true) {
let v = CGVector(dx: location.x - base.position.x, dy: location.y - base.position.y)
let angle = atan2(v.dy, v.dx)
//println( deg + 180)
let length:CGFloat = base.frame.size.height / 2
let xDist:CGFloat = sin(angle - 1.57879633) * length
let yDist:CGFloat = cos(angle - 1.57879633) * length
if (CGRectContainsPoint(base.frame, location)) {
ball.position = location
} else {
ball.position = CGPointMake( base.position.x - xDist, base.position.y + yDist)
}
ship.zRotation = angle - 1.57879633
let calcRotation : Float = Float(angle - 1.57879633) + Float(M_PI_2);
let intensity : CGFloat = 200.0 // put your value
let xVelocity = intensity * CGFloat(cosf(calcRotation))
let yVelocity = intensity * CGFloat(sinf(calcRotation))
let vector : CGVector = CGVectorMake(xVelocity, yVelocity)
//Apply force to spaceship
ship.physicsBody?.applyForce(vector)
// ends stackActive
}
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location) == self.ball {
if (stickActive == true) {
let move:SKAction = SKAction.moveTo(base.position, duration: 0.05)
move.timingMode = .EaseOut
ball.runAction(move)
}
}
}
}
//====================================================================
override func shouldAutorotate() -> Bool {
return true
}
//====================================================================
override func prefersStatusBarHidden() -> Bool {
return true
}
//====================================================================
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
//====================================================================
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
there's an issue in SceneKit where the SpriteKit overlay isn't automatically redrawn when changes are made in the 2D scene but the 3D scene is left untouched. In other words, the 2D overlay is only redrawn when the 3D view needs to be redrawn.
You can set the playing property of the SCNView to YES to fix this. Alternatively you can call -setNeedsDisplay whenever you make a change to the overlay scene.
I want to add a .dae file that is sitting in my art.assets folder. to the scene. thats it lol and in swift preferable but I'll take Objective-C as well. Thanks here some code its just the basic scene kit file Xcode gives you.
Code:
import UIKit
import QuartzCore
import SceneKit
//============================================================
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//-------------------------
let scene = SCNScene(named: "art.scnassets/GenricFootball.dae")!
let scnView = self.view as! SCNView
scnView.scene = scene
scnView.allowsCameraControl = true
scnView.showsStatistics = false
scnView.backgroundColor = UIColor.whiteColor()
let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap:")
scnView.addGestureRecognizer(tapGesture)
//--------------------------
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
//-----------------------------------------------
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
//-----------------------------------------------
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
scene.rootNode.addChildNode(ambientLightNode)
//----------------------------------------------
//_ = scene.rootNode.childNodeWithName("Bob", recursively: true)!
// _ = scene.rootNode.childNodeWithName("CampusField1", recursively: true)!
//--------------------------------------------------------
// Bob.runAction(SCNAction.repeatActionForever(SCNAction.rotateByX(0, y: 2, z: 0, duration: 1)))
}
func handleTap(gestureRecognize: UIGestureRecognizer) {
let scnView = self.view as! SCNView
let p = gestureRecognize.locationInView(scnView)
let hitResults = scnView.hitTest(p, options: nil)
if hitResults.count > 0 {
let result: AnyObject! = hitResults[0]
let material = result.node!.geometry!.firstMaterial!
SCNTransaction.begin()
SCNTransaction.setAnimationDuration(0.5)
SCNTransaction.setCompletionBlock {
SCNTransaction.begin()
SCNTransaction.setAnimationDuration(0.5)
material.emission.contents = UIColor.blackColor()
SCNTransaction.commit()
}
material.emission.contents = UIColor.yellowColor()
SCNTransaction.commit()
}
}
override func shouldAutorotate() -> Bool {
return true
}
override func prefersStatusBarHidden() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
I got to objects on the scene by using this code
Code:
let scene = SCNScene(named: "art.scnassets/GenricFootball.dae")!
let characterscene = SCNScene(named: "art.scnassets/untitled.dae")!
let monkey: SCNNode = characterscene.rootNode.childNodeWithName("Cube_001", recursively: true)!
scene.rootNode.addChildNode(monkey)
monkey.position = SCNVector3(x: 5, y: 0, z: 5)
I want to be able to rotate a camera around a cube (a collection of cubes), but for some reason, when I rotate, the rotation goes in multiple directions.
I have an object that I wish to rotate around and set this as a look at constraint. This object is in the middle of the cubes.
I have a swipe gesture recogniser that does the rotation...but it's just off. I'm missing something...
import UIKit
import QuartzCore
import SceneKit
import AVFoundation
class GameViewController: UIViewController {
var scene:SCNScene!
var tiles:[SCNNode] = [SCNNode]()
var cameraNode:SCNNode!
var centerNode:SCNNode!
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
scene = SCNScene()
let sideMaterial = SCNMaterial()
sideMaterial.diffuse.contents = UIColor.greenColor()
sideMaterial.locksAmbientWithDiffuse = true;
let geom = SCNBox(width: 32, height: 32.0, length: 32, chamferRadius: 8.0)
geom.widthSegmentCount = 16
geom.heightSegmentCount = 16
geom.lengthSegmentCount = 16
geom.materials = [sideMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial]
centerNode = SCNNode(geometry: geom)
centerNode.position = SCNVector3(x: 4*32, y: -4*32, z: -4*32)
scene.rootNode.addChildNode(centerNode)
// create and add a camera to the scene
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: -4*32, y: -4*32, z: 4*32)
cameraNode.pivot = SCNMatrix4MakeTranslation(4*32, -4*32, -4*32)
cameraNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: 1.360646)
let lookAt = SCNLookAtConstraint(target: centerNode)
//lookAt.gimbalLockEnabled = true
cameraNode.constraints = [lookAt]
cameraNode.camera?.xFov = 90
cameraNode.camera?.yFov = 90
cameraNode.camera?.zNear = 1
cameraNode.camera?.zFar = 5000
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 4*32, y: -4*32, z: 10)
scene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
scene.rootNode.addChildNode(ambientLightNode)
// retrieve the SCNView
let scnView = self.view as! SCNView
setupTiles()
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
//scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.blackColor()
// Add gestures
var gestureRecognizers = [UIGestureRecognizer]()
let swipeDownGesture = UISwipeGestureRecognizer(target: self, action: "swipe:")
swipeDownGesture.direction = UISwipeGestureRecognizerDirection.Down
gestureRecognizers.append(swipeDownGesture)
let swipeUpGesture = UISwipeGestureRecognizer(target: self, action: "swipe:")
swipeUpGesture.direction = UISwipeGestureRecognizerDirection.Up
gestureRecognizers.append(swipeUpGesture)
let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: "swipe:")
swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.Left
gestureRecognizers.append(swipeLeftGesture)
let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: "swipe:")
swipeRightGesture.direction = UISwipeGestureRecognizerDirection.Right
gestureRecognizers.append(swipeRightGesture)
if let existingGestureRecognizers = scnView.gestureRecognizers as? [UIGestureRecognizer] {
gestureRecognizers.extend(existingGestureRecognizers)
}
scnView.gestureRecognizers = gestureRecognizers
}
func swipe(gestureRecognize: UISwipeGestureRecognizer) {
var leftRight:Float = 0
var upDown:Float = 0
var amount:Float = 1.5707
switch gestureRecognize.direction
{
case UISwipeGestureRecognizerDirection.Up:
upDown = 1
break
case UISwipeGestureRecognizerDirection.Down:
upDown = -1
break
case UISwipeGestureRecognizerDirection.Left:
leftRight = -1
break
case UISwipeGestureRecognizerDirection.Right:
leftRight = 1
break
default:
break
}
SCNTransaction.begin()
SCNTransaction.setAnimationDuration(3.0)
cameraNode.rotation = SCNVector4(x: leftRight, y: upDown, z: 0, w: amount)
SCNTransaction.commit()
}
override func shouldAutorotate() -> Bool {
return true
}
override func prefersStatusBarHidden() -> 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.
}
func setupTiles()
{
for z in 0...7
{
for y in 0...7
{
for x in 0...7
{
if y > 0 && y < 7 && z > 0 && z < 7 && x > 0 && x < 7
{
continue
}
let topMaterial = SCNMaterial()
topMaterial.diffuse.contents = UIColor.whiteColor()
topMaterial.locksAmbientWithDiffuse = true;
let sideMaterial = SCNMaterial()
sideMaterial.diffuse.contents = UIColor.whiteColor()
sideMaterial.locksAmbientWithDiffuse = true;
let geom = SCNBox(width: 32, height: 32.0, length: 32, chamferRadius: 8.0)
geom.widthSegmentCount = 16
geom.heightSegmentCount = 16
geom.lengthSegmentCount = 16
geom.materials = [topMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial]
let node = SCNNode(geometry: geom)
node.position = SCNVector3(x: Float(x) * 32.0, y: -(Float(y) * 32.0), z: -(Float(z) * 32.0))
scene.rootNode.addChildNode(node)
tiles.append(node)
}
}
}
}
}
Edit:
Setting the transform instead of the rotation seems to have better effects
centerNode = SCNNode(geometry: geom)
centerNode.transform = SCNMatrix4Identity
scene.rootNode.addChildNode(centerNode)
// create and add a camera to the scene
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 8*32)
cameraNode.pivot = SCNMatrix4MakeTranslation(0, 0, -8*32)
let lookAt = SCNLookAtConstraint(target: centerNode)
lookAt.gimbalLockEnabled = true
cameraNode.constraints = [lookAt]
cameraNode.transform = SCNMatrix4Identity
//In gesture
cameraNode.transform = SCNMatrix4Rotate(cameraNode.transform, amount, upDown, leftRight, 0)