Проблема
Я разрабатываю функцию перетаскивания стрелки, чтобы растянуть ее, и столкнулся со следующими проблемами:
- Как рассчитать поворот для узла стрелки, чтобы после перетаскивания острие стрелки смотрит на конечную позицию касания?
- Как преобразовать
movementVector
из начальной в конечную позицию для расчета масштаба хвоста?
Описание
В моем случае arrowNode содержит 2 узла: head и tail .
movementVector
- 3D-вектор, содержащий разницу по расстоянию между концом и началом движения.
Опорная точка хвост сместилась к правой границе, так что, изменяя масштаб X , мы увеличиваем длина хвоста.
Xcode игровая площадка
Код
func createArrowNode() -> SCNNode {
let arrowNode = SCNNode()
arrowNode.name = "arrow"
let tail = SCNPlane(width: 3, height: 2)
let tailNode = SCNNode(geometry: tail)
tailNode.name = "tail"
tailNode.position = SCNVector3(0.25, 0, 0)
// Move pivot to the edge of the tail
tailNode.pivot = SCNMatrix4MakeTranslation(Float(tail.width / 2), 0, 0)
tailNode.renderingOrder = 2
let head = SCNPlane(width: 5.2, height: 5.2)
let headNode = SCNNode(geometry: head)
headNode.name = "head"
headNode.renderingOrder = 1
arrowNode.addChildNode(tailNode)
arrowNode.addChildNode(headNode)
return arrowNode
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let sceneView = view as? SCNView,
let touchLocation = touches.first?.location(in: sceneView) else { return }
let hitTestOptions: [SCNHitTestOption : Any] = [
.boundingBoxOnly: true,
]
guard var node = sceneView.hitTest(touchLocation, options: hitTestOptions).first?.node else { return }
// use arrow node container
node = node.name == "tail" || node.name == "head"
? node.parent!
: node
lastTouchPosition = node.worldPosition
touchedNode = node
touchStartZ = CGFloat(sceneView.projectPoint(lastTouchPosition!).z)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let sceneView = view as? SCNView,
let touchLocation = touches.first?.location(in: sceneView) else { return }
guard let previousPosition = lastTouchPosition,
let touchStartZ = touchStartZ,
let touchedNode = touchedNode else { return }
let current3DPosition = SCNVector3(touchLocation.x, touchLocation.y, touchStartZ)
let worldTouchPosition = sceneView.unprojectPoint(current3DPosition)
lastTouchPosition = worldTouchPosition
let movementVector = worldTouchPosition - previousPosition
changeArrow(movementVector: movementVector, arrowNode: touchedNode )
}
Спасибо!