ARKit-带你走进全新的世界(三:追踪/距离感应/AR尺子)

简介:

上篇回顾:

在ARKit(光线与动画处理),使用Objective-C在一个正常的项目开启的一个AR项目,实现一个solar system的demo,实现太阳的公转与自转,包括之间的关系,各个节点谁是谁的子节点,设置地月节点,然后添加黄道,把动画添加在黄道节点,处理地球与太阳的关系,当然在动画的处理之后,添加光照度与更全面的渲染

原文地址:  http://www.2bjs.com

欢迎加入q群 150731459

本篇介绍:

 拿到三维坐标点,拿到相机的实时位置(两个分类),计算距离:

//        A(x1,y1,z1),B(x2,y2,z2),则A,B之间的距离为

//        d=√[(x1-x2)^2+(y1-y2)^2+(z1-z2)^2]

之后我们来记录起始点,此处写了一个Line类,在其中实现其中主要的角色以及实现的主要场景,创建SCNGeometrySource物件,创建SCNGeometryElement把创建的顶点连起来,用line的方式来画一条线(GPU操作可以减少CPU负担),然后获取到实时测试的距离,在我们的现实世界中将你所在的初始原点位置,和你结束的位置的距离来测量出来

正文:

效果展示:


使用示例:


实现思路:

1.搭建基本环境,开启全局追踪

2.拿到三维坐标点

3.拿到相机实时位置

4.初始化场景与角色

5.实时跟踪,处理事件,完善

步骤:

1.搭建基本框架

session.run方法开启全局追踪<提问:全局追踪失效?>

搭建基本框架基本控件属性

@IBOutlet weak var sceneV: ARSCNView!

@IBOutlet weak var InfoL: UILabel!//这个label的命名大家不要介意,手残了

@IBOutlet weak var targetIM: UIImageView!

var session = ARSession()

var configuration = ARWorldTrackingConfiguration()

2.代理,全局的追踪状态

func session(_ session: ARSession, didFailWithError error: Error) {

InfoL.text = "错误"

}

func sessionWasInterrupted(_ session: ARSession) {

InfoL.text = "中断~"

}

func sessionInterruptionEnded(_ session: ARSession) {

InfoL.text = "结束"

}

4.BXARSCNView+Extension类来拿三维坐标

func worldVector(for position:CGPoint) ->SCNVector3?{

//result

let results = hitTest(position, types: [.featurePoint])

guard let result = results.first else {

return nil

}

//-->返回相机的位置

return SCNVector3.positionTranform(result.worldTransform)

}

此处设置结果(let results)的时候,使用了types,这里相机与物件之间的距离,用来搜索ARSession检测到的锚点,真实世界中的对象不是view中的SceneKit里面的内容,假设找内容的话用(option)

5.BXSCNVector3 + Extension将坐标的x,y,z回传,计算距离,画线

回传xyz

static func positionTranform(_ tranform:matrix_float4x4) -> SCNVector3{

//将坐标的x,y,z轴回传出去

return SCNVector3Make(tranform.columns.3.x, tranform.columns.3.y, tranform.columns.3.z)

}

计算距离

func distance(for vector:SCNVector3) -> Float {

let distanceX = self.x-vector.x//现在的位置减去出发的位置

let distanceY = self.y-vector.y

let distanceZ = self.z-vector.z

return sqrt((distanceX * distanceX)+(distanceY * distanceY)+(distanceZ * distanceZ))

}

画线

func line(to vector:SCNVector3,color:UIColor) -> SCNNode {

let indices : [UInt32] = [0,1]//指数

let source = SCNGeometrySource(vertices: [self,vector]) // 创建一个几何容器

let element = SCNGeometryElement(indices: indices, primitiveType: .line)//用线的方式来创造一个几何元素(线)

let geomtry = SCNGeometry(sources: [source], elements: [element])//几何

geomtry.firstMaterial?.diffuse.contents = color//渲染颜色

let node = SCNNode(geometry: geomtry)//返回一个节点

return node

}

6.初始化主要角色与场景

定义

var color = UIColor.red,

var startNode : SCNNode

var endNode : SCNNode

var textNode : SCNNode

var text : SCNText

var lineNode : SCNNode?

let sceneView: ARSCNView

let startVector: SCNVector3

初始化:创建节点-添加子节点

self.sceneView = sceneView

self.startVector = startVector

self.unit = unit

let dot = SCNSphere(radius: 0.5)

dot.firstMaterial?.diffuse.contents = color

dot.firstMaterial?.lightingModel = .constant//光照,表面看起来都是一样的光亮,不会产生阴影

dot.firstMaterial?.isDoubleSided = true//两面都很亮

startNode = SCNNode(geometry: dot)

startNode.scale = SCNVector3(1/500.0,1/500.0,1/500.0)

startNode.position = startVector

sceneView.scene.rootNode.addChildNode(startNode)

endNode = SCNNode(geometry: dot)//这里只需要先创建出来,稍后添加

endNode.scale = SCNVector3(1/500.0,1/500.0,1/500.0)//这里也有坑

text = SCNText(string: "", extrusionDepth: 0.1)

text.font = .systemFont(ofSize: 5)

text.firstMaterial?.diffuse.contents = color

text.firstMaterial?.lightingModel = .constant

text.firstMaterial?.isDoubleSided = true

text.alignmentMode = kCAAlignmentCenter//位置

text.truncationMode = kCATruncationMiddle//........

let textWrapperNode = SCNNode(geometry: text)

textWrapperNode.eulerAngles = SCNVector3Make(0, .pi, 0) // 数字对着自己

textWrapperNode.scale = SCNVector3(1/500.0,1/500.0,1/500.0) 

textNode = SCNNode()

textNode.addChildNode(textWrapperNode)//添加到包装节点上

let constraint = SCNLookAtConstraint(target: sceneView.pointOfView)//来一个约数

constraint.isGimbalLockEnabled = true

textNode.constraints = [constraint]

sceneView.scene.rootNode.addChildNode(textNode)

SCNVector3(A representation of a three-component vector.

SceneKit uses three-component vectors for a variety of purposes, such as

describing node or vertex positions, surface normals, and scale or translation

transforms. The different vector components should be interpreted based on the

context in which the vector is being used.

Important

In macOS, the x, y, and z fields in this structure are CGFloat values. In iOS,

tvOS, and watchOS, these fields are Float values.)此处我们来描述节点或者是顶点的位置时候注意要用CGFloat-->否则会出现意想不到的情况(消失不见????)

7.处理更新文字

lineNode?.removeFromParentNode()//移除掉所有线

lineNode = startVector.line(to: vector, color: color)

sceneView.scene.rootNode.addChildNode(lineNode!)

//更新文字a

text.string = distance(to: vector)

//文字位置

textNode.position = SCNVector3((startVector.x + vector.x) / 2.0 , (startVector.y + vector.y) / 2.0 ,(startVector.z + vector.z) / 2.0 )

endNode.position = vector

if endNode.parent == nil {

sceneView.scene.rootNode.addChildNode(endNode)

}

8.点击屏幕的时候,进入测试状态,开始画线,记录开始点和结束点

当然我们追踪显示时间需要在主线程中

DispatchQueue.main.async {}

优化:

1.全局追踪的高级用法:在生命周期view将要显示的时候移除所有锚点,并且重新开启追中效率会大大提高,当生命周期view将要消失的时候,我们所追踪的位置并不一定还留在原来的位置,所以说我们移掉所有锚点之后在次来一次追踪,效率是不是会提高很多-->resetTracking  removeExistingAnchors

2.Equatable协议防止重复:

public static func == (lhs: SCNVector3, rhs: SCNVector3) -> Bool {

//当左边的与右边的相等

return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z)

}

3.移除remove

line.remove(),当点击Reset的时候进行清除

总结:

本文主要难点,在于三维坐标点的获取,相机的实时位置,距离的计算以及画线

最后为大家献上本文代码地址,我在git中的demo中也写了注释,大家可以仔细看一下demo,欢迎大家下载,star

欢迎加入q群 150731459

C博客地址

转载请注明出处   原文地址:http://www.2bjs.com  作者Fujian Bi

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容