我正在使用iOS中的ARKit,并且想减小现实世界中实际对象的大小。用捏手势可以调整对象的大小,但是当我点击时,我想放置缩小的对象。 在SceneKit编辑器中,如果我们选择对世界进行编辑,则缩放选项不可用。那么可以通过程序编辑世界空间中3D对象的比例尺吗?
答案 0 :(得分:0)
大约1.5年前我做了这个。我不能保证它仍然有效。但首先,您需要添加听众:
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(adjustWindow))
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(adjustWindow))
let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(adjustWindow))
let tapGesture = UIPanGestureRecognizer(target: self, action: #selector(adjustWindow))
pinchGesture.cancelsTouchesInView = false
rotateGesture.cancelsTouchesInView = false
panGesture.cancelsTouchesInView = false
tapGesture.cancelsTouchesInView = false
tapGesture.minimumNumberOfTouches = 2
sceneView.addGestureRecognizer(panGesture)
sceneView.addGestureRecognizer(pinchGesture)
sceneView.addGestureRecognizer(rotateGesture)
sceneView.addGestureRecognizer(tapGesture)
然后再处理一些事情:
@objc func adjustWindow(_ gesture: UIGestureRecognizer) {
// Fetch location for touch in sceneView
let location: CGPoint = gesture.location(in: sceneView)
// Fetch targets at the current location
let hits = self.sceneView.hitTest(location, options: nil)
// Check if it's a node and it's a window node that has been touched
guard let node = hits.first?.node, node.name == "window" else {return}
// Rotate the window if the motion is of the rotation kind
if let rotateRecognizer = gesture as? UIRotationGestureRecognizer {
let action = SCNAction.rotateBy(x: 0, y: rotateRecognizer.rotation/200 , z: 0, duration: 0.1)
node.runAction(action)
return
}
// Make sure user is using 1 finger to move the view
if gesture.numberOfTouches == 1 {
switch gesture.state {
case .failed, .cancelled, .ended:
startPosition = CGPoint(x: 0, y: 0)
break
case .began:
// Save start position, so that we can check how far the user have moved
startPosition = location
case .changed:
// Fetch new x and y position
// Note that 1 point is 1 meter and since we want minimal movement we divide it greatly
let deltaX = Float(location.x-startPosition.x)/400
let deltaY = Float(location.y-startPosition.y)/20000
// Transform and apply the new location
// You can either move the axises of the nodes parents by using "node.scale = SCNVector(x,y,z)"
// Or you can move the axises of the node itself by transforming the nodes reality as below
// https://stackoverflow.com/questions/43237805/how-to-move-a-rotated-scnnode-in-scenekit
let box = node.transform
let translation = SCNMatrix4MakeTranslation(-deltaX, deltaY, 1)
let newTrans = SCNMatrix4Mult(translation, box)
node.transform = newTrans
node.localTranslate(by: SCNVector3Make(-deltaX, deltaY, 1))
// Set new location
startPosition = location
default:
break
}
// Make sure user is using 2 fingers for scaling the view
} else if gesture.numberOfTouches == 2, let pinchGesture = gesture as? UIPinchGestureRecognizer {
switch pinchGesture.state {
case .began:
// Save start position, so that we can check how far the user have moved
startPosition = location
case .changed:
// MARK: - Scaling
// Scaling is unaffected as long as it scales with it's own current value hence we fetch
// node.scale locations where we want it to be unaffected
// Scale vertically if user moved more than 4 points
// https://stackoverflow.com/questions/44850927/scaling-a-scnnode-in-runtime-using-the-pan-gesture
if abs(location.y-startPosition.y) > 4 {
let pinchScaleY: CGFloat = pinchGesture.scale * CGFloat((node.scale.y))
node.scale = SCNVector3Make(node.scale.x, Float(pinchScaleY), node.scale.z)
// Else scale horizontally, if the user moved more than 4 points horizontally
} else if abs(location.x-startPosition.x) > 4 {
let pinchScaleX: CGFloat = pinchGesture.scale * CGFloat((node.scale.x))
node.scale = SCNVector3Make(Float(pinchScaleX), node.scale.y, node.scale.z)
}
pinchGesture.scale = 1
default:
break
}
} else if let panGesture = gesture as? UIPanGestureRecognizer, panGesture.numberOfTouches == 2 {
switch panGesture.state {
case .failed, .cancelled, .ended:
startPosition = CGPoint(x: 0, y: 0)
break
case .began:
// Save start position, so that we can check how far the user have moved
startPosition = location
case .changed:
// Fetch new x and y position
let deltaZ = Float(location.y-startPosition.y)/2000
// Set new position
node.position = SCNVector3Make(node.position.x, node.position.y, node.position.z+deltaZ)
// Set new location
startPosition = location
default:
break
}
}
}
我知道这包含用于移动节点,旋转节点以及所有内容的代码。但最关键的是中间部分:
else if gesture.numberOfTouches == 2, let pinchGesture = gesture as? UIPinchGestureRecognizer
答案 1 :(得分:0)
是的,这是可能的-您可以使用节点的scale
参数(node.scale
)来调整节点的比例。