I can programmatically create a 3D cube in iOS using the code below. However, I need to use gestures to define its size. With a pinch gesture
I'd like to build a base of cube in XZ axis. And with a drag gesture
I'd like to build a height of cube in Y axis.
The question is: How to construct a 3D cube using these two gestures?
Here's my code:
import UIKit
import SceneKit
class GameViewController: UIViewController {
var scnView: SCNView!
var scnScene: SCNScene!
var cameraNode: SCNNode!
override func viewDidLoad() {
super.viewDidLoad()
self.setupView()
self.setupScene()
self.setupCamera()
self.spawnShape()
}
override func shouldAutorotate() -> Bool {
return true
}
override func prefersStatusBarHidden() -> Bool {
return true
}
func setupView() {
scnView = self.view as! SCNView
scnView.allowsCameraControl = true
scnView.autoenablesDefaultLighting = true
}
func setupScene() {
scnScene = SCNScene()
scnView.scene = scnScene
scnScene.background.contents = UIImage(named: "bgTexture.png")
}
func setupCamera() {
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 12)
scnScene.rootNode.addChildNode(cameraNode)
}
func spawnShape() {
var geometry: SCNGeometry = SCNBox(width: 1.0,
height: 1.0,
length: 1.0,
chamferRadius: 0.1)
let geometryNode = SCNNode(geometry: geometry)
scnScene.rootNode.addChildNode(geometryNode)
}
}
Here's how I tried to implement UIPinchGestureRecognizer() and UIPanGestureRecognizer().
var pinchGesture = UIPinchGestureRecognizer()
var dragGesture = UIPanGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
setupView()
setupScene()
setupCamera()
spawnShape()
self.scnView.userInteractionEnabled = true
self.scnView.multipleTouchEnabled = true
pinchGesture = UIPinchGestureRecognizer(target: self,
action: #selector(pinchRecognized))
dragGesture = UIPanGestureRecognizer(target: self,
action: #selector(panRecognized))
self.scnView.addGestureRecognizer(self.pinchGesture)
self.scnView.addGestureRecognizer(self.dragGesture)
}
@IBAction func pinchRecognized(pinch: UIPinchGestureRecognizer) { ... }
@IBAction func panRecognized(pan: UIPanGestureRecognizer) { ... }
You can use UIGestureRecognizers
to accomplish what you are looking for.
in your ViewDidLoad()
add your recognizer:
// Add Gesture recognizers
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(scaleSizeOfGeometry(sender:)))
scnView.addGestureRecognizer(pinch)
Incremental scaling in the XZ directions can now be accomplished by using:
func scaleSizeOfGeometry(sender: UIPinchGestureRecognizer) {
let scale = Float(sender.scale)
referenceToGeometry?.scale.x *= scale
referenceToGeometry?.scale.z *= scale
sender.scale = 1.0
}
You have to reference the geometry you want to scale somehow. For example with a variable referenceToGeometry : SCNNode?
that is set in your spawnGeometry()
:
referenceToGeometry = geometryNode
The UIPanGestureRecognizer
is a bit more tricky since you can use a velocity or a translation to scale in the Y direction. In your viewDidLoad()
add the gesture recognizer:
let pan = UIPanGestureRecognizer(target: self, action: #selector(scaleHeightOfGeometry(sender:)))
scnView.addGestureRecognizer(pan)
And in your function use either the velocity or the translation:
func scaleHeightOfGeometry(sender: UIPanGestureRecognizer) {
// y : sender.translation(in: self.scnView).y
// v : sender.velocity(in: self.scnView).y
}
You will have to extract a multiplier to your own liking from either of these. For example by storing the y[i-1] and checking the difference between the two, than adding the difference to the height of your geometry and storing the newValue as the y[i-1]th value.
EDIT:
To add to the post, you can use UIGestureRecognizer
states for more advanced/finetuned versions of this.