我想在不在屏幕上时将箭头放在屏幕边缘指向锚点的方向.我需要知道节点是否位于平截头体的左侧或右侧.
我现在正在这样做,但是它表示如果不是,并且X值看起来不对,那么引脚是可见的吗?也许渲染器视锥体与屏幕相机不匹配?
var deltaTime = TimeInterval() public func renderer(_ renderer: SCNSceneRenderer,updateAtTime time: TimeInterval) { deltaTime = time - lastUpdateTime if deltaTime>1{ if let annotation = annotationsByNode.first { let node = annotation.key.childNodes[0] if !renderer.isNode(node,insIDeFrustumOf: renderer.pointOfVIEw!) { print("Pin is not visible"); }else { print("Pin is visible"); } let pnt = renderer.projectPoint(node.position) print("pos ",pnt.x," ",renderer.pointOfVIEw!.position) } lastUpdateTime = time } }
更新:代码用于显示节点是否可见,如何判断节点相对于相机平截头的左或右方向?
UPDATE2!正如Bhanu Birani的建议答案
let screenWIDth = UIScreen.main.bounds.wIDthlet screenHeight = UIScreen.main.bounds.heightlet leftPoint = CGPoint(x: 0,y: screenHeight/2)let rightPoint = CGPoint(x: screenWIDth,y: screenHeight/2)let leftWorldPos = renderer.unprojectPoint(SCNVector3(leftPoint.x,leftPoint.y,0))let rightWorldPos = renderer.unprojectPoint(SCNVector3(rightPoint.x,rightPoint.y,0))let distanceleft = node.position - leftWorldPoslet distanceRight = node.position - rightWorldPoslet dir = (isVisible) ? "visible" : ( (distanceleft.x<distanceRight.x) ? "left" : "right")
我最终使用了屏幕左右两侧的Bhanu Birani的想法,但是我获得了不同的世界位置,unProjectPoint并且还获得了距离的标量值,我将其与左/右方向进行比较.也许有更好的方法,但它对我有用
public func renderer(_ renderer: SCNSceneRenderer,updateAtTime time: TimeInterval) { deltaTime = time - lastUpdateTime if deltaTime>0.25{ if let annotation = annotationsByNode.first { guard let pointOfVIEw = renderer.pointOfVIEw else {return} let node = annotation.key.childNodes[0] let isVisible = renderer.isNode(node,insIDeFrustumOf: pointOfVIEw) let screenWIDth = UIScreen.main.bounds.wIDth let screenHeight = UIScreen.main.bounds.height let leftPoint = CGPoint(x: 0,y: screenHeight/2) let rightPoint = CGPoint(x: screenWIDth,y: screenHeight/2) let leftWorldPos = renderer.unprojectPoint(SCNVector3(leftPoint.x,0)) let rightWorldPos = renderer.unprojectPoint(SCNVector3(rightPoint.x,0)) let distanceleft = node.worldposition.distance(vector: leftWorldPos) let distanceRight = node.worldposition.distance(vector: rightWorldPos) //let pnt = renderer.projectPoint(node.worldposition) //guard let pnt = renderer.pointOfVIEw!.convertposition(node.position,to: nil) else {return} let dir = (isVisible) ? "visible" : ( (distanceleft<distanceRight) ? "left" : "right") print("dir",dir,leftWorldPos,rightWorldPos) lastDir=dir delegate?.nodeposition?(node:node,pos: dir) }else { delegate?.nodeposition?(node:nil,pos: lastDir ) } lastUpdateTime = time }extension SCNVector3{ /** * Returns the length (magnitude) of the vector described by the SCNVector3 */ func length() -> float { return sqrtf(x*x + y*y + z*z) } /** * Calculates the distance between two SCNVector3. Pythagoras! */ func distance(vector: SCNVector3) -> float { return (self - vector).length() }}从以下屏幕位置投射光线:
> leftPoint = CGPoint(0,screenHeight / 2)(屏幕中间左侧)
> rightPoint = CGPoint(screenWIDth,screenHeight / 2)(屏幕右侧)
将CGPoint转换为世界位置:
> leftWorldPos = convertCGPointToWorldposition(leftPoint)
> rightWorldPos = convertCGPointToWorldposition(rightPoint)
计算两个世界位置的节点距离:
> distanceleft = node.position – leftWorldPos
> distanceRight = node.position – rightWorldPos
比较距离以找到到节点的最短距离.使用最短距离矢量来定位对象的方向箭头.
以下是来自tsukimi的代码,用于检查对象是在屏幕的右侧还是在左侧:
public func renderer(_ renderer: SCNSceneRenderer,pos: lastDir ) } lastUpdateTime = time }
以下是帮助对vector执行 *** 作的类
extension SCNVector3 { init(_ vec: vector_float3) { self.x = vec.x self.y = vec.y self.z = vec.z } func length() -> float { return sqrtf(x * x + y * y + z * z) } mutating func setLength(_ length: float) { self.normalize() self *= length } mutating func setMaximumLength(_ maxLength: float) { if self.length() <= maxLength { return } else { self.normalize() self *= maxLength } } mutating func normalize() { self = self.normalized() } func normalized() -> SCNVector3 { if self.length() == 0 { return self } return self / self.length() } static func positionFromtransform(_ transform: matrix_float4x4) -> SCNVector3 { return SCNVector3Make(transform.columns.3.x,transform.columns.3.y,transform.columns.3.z) } func frIEndlyString() -> String { return "(\(String(format: "%.2f",x)),\(String(format: "%.2f",y)),z)))" } func dot(_ vec: SCNVector3) -> float { return (self.x * vec.x) + (self.y * vec.y) + (self.z * vec.z) } 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) }}extension SCNVector3{ func distance(receiver:SCNVector3) -> float{ let xd = receiver.x - self.x let yd = receiver.y - self.y let zd = receiver.z - self.z let distance = float(sqrt(xd * xd + yd * yd + zd * zd)) if (distance < 0){ return (distance * -1) } else { return (distance) } }}
以下是将抽头位置或任何CGPoint转换为世界变换的代码段.
@objc func handleTap(_ sender: UITapGestureRecognizer) { // Take the screen space tap coordinates and pass them to the hitTest method on the ARSCNVIEw instance let tapPoint = sender.location(in: sceneVIEw) let result = sceneVIEw.hitTest(tapPoint,types: ARHitTestResult.ResultType.existingPlaneUsingExtent) // If the intersection ray passes through any plane geometry they will be returned,with the planes // ordered by distance from the camera if (result.count > 0) { // If there are multiple hits,just pick the closest plane if let hitResult = result.first { let finalposition = SCNVector3Make(hitResult.worldtransform.columns.3.x + insertionXOffset,hitResult.worldtransform.columns.3.y + insertionYOffset,hitResult.worldtransform.columns.3.z + insertionZOffset ); } }}
以下是在没有找到飞机时获得命中测试结果的代码.
// check what nodes are tappedlet p = gestureRecognize.location(in: scnVIEw)let hitResults = scnVIEw.hitTest(p,options: [:])// check that we clicked on at least one objectif hitResults.count > 0 { // retrIEved the first clicked object let result = hitResults[0] }总结
以上是内存溢出为你收集整理的swift – arkit锚点或节点在相机中可见并且坐在平截头体的左侧或右侧全部内容,希望文章能够帮你解决swift – arkit锚点或节点在相机中可见并且坐在平截头体的左侧或右侧所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)