Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danmonaghan/f4eafa84cfb0bd22ec68f5b55ba8aeee to your computer and use it in GitHub Desktop.
Save danmonaghan/f4eafa84cfb0bd22ec68f5b55ba8aeee to your computer and use it in GitHub Desktop.
//
// GameViewController.swift
// StackTrackBall
//
// Created by Dan Monaghan on 9/04/22.
//
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController {
var cameraOrbit = SCNNode()
let orbitCameraNode = SCNNode()
let orbitCamera = SCNCamera()
//HANDLE PAN CAMERA
var lastWidthRatio: Float = 0
var lastHeightRatio: Float = 0.2
var fingersNeededToPan = 1
var maxWidthRatioRight: Float = 1000
var maxWidthRatioLeft: Float = 1000
var maxHeightRatioXDown: Float = 1000
var maxHeightRatioXUp: Float = 1000
//HANDLE PINCH CAMERA
var pinchAttenuation = 20.0 //1.0: very fast ---- 100.0 very slow
var lastFingersNumber = 0
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLight.LightType.omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLight.LightType.ambient
ambientLightNode.light!.color = UIColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)
//Create a camera like Rickster said
// let camera = SCNCamera()
// camera.usesOrthographicProjection = true
// camera.orthographicScale = 9
// camera.zNear = 0
// camera.zFar = 100
// let cameraNode = SCNNode()
// cameraNode.position = SCNVector3(x: 0, y: 0, z: 50)
// cameraNode.camera = camera
// let cameraOrbit = SCNNode()
// cameraOrbit.addChildNode(cameraNode)
// cubeScene.rootNode.addChildNode(cameraOrbit)
//
orbitCamera.zNear = 1
orbitCamera.zFar = 100
orbitCamera.motionBlurIntensity = 0.6
orbitCameraNode.position = SCNVector3(x: 0, y: 0, z: 4)
orbitCameraNode.camera = orbitCamera
cameraOrbit = SCNNode()
cameraOrbit.addChildNode(orbitCameraNode)
scene.rootNode.addChildNode(cameraOrbit)
//initial camera setup
self.cameraOrbit.eulerAngles.y = Float(-2 * Float.pi) * lastWidthRatio
self.cameraOrbit.eulerAngles.x = Float(-Float.pi) * lastHeightRatio
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene
scnView.showsStatistics = true
//allows the user to manipulate the camera
scnView.allowsCameraControl = false //not needed
// add a tap gesture recognizer
let panGesture = UIPanGestureRecognizer(target: self, action:#selector(handlePan))
scnView.addGestureRecognizer(panGesture)
// add a pinch gesture recognizer
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
scnView.addGestureRecognizer(pinchGesture)
let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate))
scnView.addGestureRecognizer(rotateGesture)
}
let dollySpeed : Float = 2000
let zRollModifier : Float = 5
let panModifier = 100
let pinchModifier : Float = 15
let maxZoomIn : Float = -1000.0
let maxZoomOut : Float = 1000.0
@objc func handleRotate(recognizer: UIRotationGestureRecognizer) {
let scale = recognizer.velocity
print("scale =\(scale)")
cameraOrbit.eulerAngles.z += Float(scale / CGFloat(zRollModifier)).radians
}
@objc func handlePan(gestureRecognize: UIPanGestureRecognizer) {
if gestureRecognize.numberOfTouches == 1 {
let numberOfTouches = gestureRecognize.numberOfTouches
let translation = gestureRecognize.velocity(in: gestureRecognize.view!)
cameraOrbit.eulerAngles.y -= Float(translation.x/CGFloat(panModifier)).radians
cameraOrbit.eulerAngles.x -= Float(translation.y/CGFloat(panModifier)).radians
}
if gestureRecognize.numberOfTouches == 2 {
let scale = gestureRecognize.velocity(in: gestureRecognize.view!)
print("scale =\(scale)")
let translation = gestureRecognize.translation(in: gestureRecognize.view!)
let xx = orbitCameraNode.position.x - Float(scale.x) / dollySpeed
if xx < maxZoomOut, xx > maxZoomIn {
orbitCameraNode.position.x = xx
}
let yy = orbitCameraNode.position.y + Float(scale.y) / dollySpeed
if yy < maxZoomOut, yy > maxZoomIn {
orbitCameraNode.position.y = yy
}
}
}
@objc func handlePinch(recognizer: UIPinchGestureRecognizer) {
// guard let camera = cameraOrbit.childNodes.first else {
// return
// }
let scale = recognizer.velocity
print("scale =\(scale)")
let z = orbitCameraNode.position.z - Float(scale)/Float(pinchModifier)
if z < maxZoomOut, z > maxZoomIn {
orbitCameraNode.position.z = z
}
}
//@objc func handlePinch(gestureRecognize: UIPinchGestureRecognizer) {
// let pinchVelocity = Double.init(gestureRecognize.velocity)
// //print("PinchVelocity \(pinchVelocity)")
//
// camera.orthographicScale -= (pinchVelocity/pinchAttenuation)
//
// if camera.orthographicScale <= 0.5 {
// camera.orthographicScale = 0.5
// }
//
// if camera.orthographicScale >= 10.0 {
// camera.orthographicScale = 10.0
// }
//
//}
//override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
// return .Landscape
//}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
extension Float {
var radians: Float {
return self * .pi / 180
}
var degrees: Float {
return self * 180 / .pi
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment