如何使ARNode
指向ARAnchor
?
我想使用art.scnassets/ship.scn
在屏幕中央显示,并指向我刚刚放置在场景中某处的对象。
/// ViewController Class
func placeObject() {
let screenCentre : CGPoint = CGPoint(x: self.sceneView.bounds.midX, y: self.sceneView.bounds.midY)
guard let hitTestResult = sceneView.hitTest(screenCentre, types: [.featurePoint]).first else { return }
// Place an anchor for a virtual character.
let anchor = ARAnchor(name: identifierString, transform: hitTestResult.worldTransform)
sceneView.session.add(anchor: anchor)
// add to item model
ItemModel.shared.anchors.append((identifierString, anchor)
}
func showDirection(of object: ARAnchor) { // object: saved anchor
if !Guide.shared.isExist {
let startPoint = SCNVector3(0, 0 , -1)
let targetPoint = SCNVector3(object.transform.columns.3.x, object.transform.columns.3.y, object.transform.columns.3.z)
let guideNode = Guide.shared.setPosition(from: startPoint, to: targetPoint)
// add the ship in the center of the view
sceneView.pointOfView?.addChildNode(guideNode)
}
}
/// Guide Class
func setPosition(from start: SCNVector3, to target: SCNVector3) -> SCNNode {
isExist = true
guideNode.position = start
targetPosition = target
// create target node from saved anchor
let desNode = SCNNode()
desNode.position = targetPosition
let lookAtConstraints = SCNLookAtConstraint(target: desNode)
guideNode.constraints = [lookAtConstraints]
return guideNode
}
// MARK: - ARSCNViewDelegate
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
if let name = anchor.name, name.hasPrefix(identifierString) {
// Create 3D Text
let textNode: SCNNode = createNewBubbleParentNode(identifierString)
node.addChildNode(textNode)
}
}
我尝试了SCNLookAtConstraint
,但没有按预期运行,有任何建议吗?
答案 0 :(得分:3)
我不知道这对您有没有帮助。 (否则,我将删除答案)
所以我也遇到了同样的问题。我在两个SCNVector对象之间绘制墙的地方。问题是墙壁是双面的,因此在某些情况下会翻转相机可见的部分。
like如果您从两个向量绘制墙,然后添加另一个具有相同欧拉角的节点(平面节点),则节点(平面)会垂直翻转。
我已经搜索了许多解决方案,并尝试了许多事情,但这对我有用。
class func node(from:SCNVector3,
to:SCNVector3,height:Float,needToAlignToCamera:Bool) -> SCNNode {
let distance = MathHelper().getMeasurementBetween(vector1: from, and: to)
let wall = SCNPlane(width: CGFloat(distance),
height: CGFloat(height))
wall.firstMaterial = wallMaterial()
let node = SCNNode(geometry: wall)
// always render before the beachballs
node.renderingOrder = -10
// HERE IS MAGIC LINES
//============================================
let normalizedTO = to.normalized()
let normalizedFrom = from.normalized()
let angleBetweenTwoVectors = normalizedTO.cross(normalizedFrom)
var from = from
var to = to
if angleBetweenTwoVectors.y > 0 && needToAlignToCamera {
let temp = from
from = to
to = temp
}
//============================================
node.position = SCNVector3(from.x + (to.x - from.x) * 0.5,
from.y + height * 0.5,
from.z + (to.z - from.z) * 0.5)
// orientation of the wall is fairly simple. we only need to orient it around the y axis,
// and the angle is calculated with 2d math.. now this calculation does not factor in the position of the
// camera, and so if you move the cursor right relative to the starting position the
// wall will be oriented away from the camera (in this app the wall material is set as double sided so you will not notice)
// - obviously if you want to render something on the walls, this issue will need to be resolved.
node.eulerAngles = SCNVector3(0, -atan2(to.x - node.position.x, from.z - node.position.z) - Float.pi * 0.5, 0)
return node
}
扩展名
func cross(_ vec: SCNVector3) -> SCNVector3 {
return SCNVector3(self.y * vec.z - self.z * vec.y, self.z * vec.x - self.x * vec.z, self.x * vec.y - self.y * vec.x)
}
func normalized() -> SCNVector3 {
if self.length() == 0 {
return self
}
return self / self.length()
}
答案 1 :(得分:2)
void CROpportunity_RowPersisting(PXCache sender, PXRowPersistingEventArgs e, PXRowPersisting del)
{
// Don't call save action or persist
// Just modify data and let the system save
}
更新通过委托方法ARKit
提供的锚点和相应节点的位置
因此约束条件的想法是正确的,但是您需要通过委托方法提供节点,而不是直接将其添加到场景中。
类似的东西-
renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode?
答案 2 :(得分:1)
我注意到SCNLookAtConstraint
在手机的方向平行于水平线时有效。 (屏幕朝上)
这行代码神奇! guideNode.pivot = SCNMatrix4Rotate(guideNode.pivot, Float.pi, 0, 1, 1)
如果您有兴趣,请参见here。
public func showDirection(of object: arItemList) {
guard let pointOfView = sceneView.pointOfView else { return }
// remove previous instruction
for node in pointOfView.childNodes {
node.removeFromParentNode()
}
// target
let desNode = SCNNode()
let targetPoint = SCNVector3.positionFromTransform(object.1.transform)
desNode.worldPosition = targetPoint
// guide
let startPoint = SCNVector3(0, 0 , -1.0)
let guideNode = loadObject()
guideNode.scale = SCNVector3(0.7, 0.7, 0.7)
guideNode.position = startPoint
let lookAtConstraints = SCNLookAtConstraint(target: desNode)
lookAtConstraints.isGimbalLockEnabled = true
// Here's the magic
guideNode.pivot = SCNMatrix4Rotate(guideNode.pivot, Float.pi, 0, 1, 1)
guideNode.constraints = [lookAtConstraints]
pointOfView.addChildNode(guideNode)
}