ARkit 实战教程(Xcode开发)

ARkit 实战教程(Xcode开发)


ARKit 最近在开发圈实在是火,ios 开发者可以快速的进行增强现实的开发,简化了许多步骤,之前了,我们AR酱也出了相应的ARKit 系列教程,今天了算是ARKit 的实战教程番外篇,我们实现一些网上比较流行的一些AR功能。

ps:代码地址:http://www.arparticles.com/portal.php?mod=view&aid=107

基础:现实模型

基础效果演示:

打开Xcode,新建一个AR项目

这次我们用SceneKit 来渲染3D内容。

进入项目之后会有个smaple project,我们可以尝试着运行:

我们使用SceneKit绘制一个3D立方体。SceneKit有几个基本类,SCNScene是所有3D模型的容器。要向场景添加内容,你首先创建几何,几何可以是复杂的形状,或简单的像球体,多维数据集,平面等。然后,将几何模型放在在场景节点中,并将其添加到场景中。然后,SceneKit将遍历场景图并呈现内容。

- (void)viewDidLoad {

[super viewDidLoad];

SCNScene *scene = [SCNScene new];

SCNBox *boxGeometry = [SCNBox

boxWithWidth:0.1

height:0.1

length:0.1

chamferRadius:0.0];

SCNNode *boxNode = [SCNNode nodeWithGeometry:boxGeometry];

boxNode.position = SCNVector3Make(0, 0, -0.5);

[scene.rootNode addChildNode: boxNode];

self.sceneView.scene = scene;

}

ARKit和SceneKit的坐标系如下所示:

当ARSession启动时,计算出的相机位置最初设置为X = 0,Y = 0,Z = 0。

们可以看到立方体的两面,我们可以稍后添加一些更高级的照明,但现在我们可以在SCNScene实例上设置autoenablesDefaultLighting :

self.sceneView.autoenablesDefaultLighting = YES;

进阶:平面检测+可视化

效果演示:

在我们开始之前,将一些调试信息添加到程序中,即渲染ARKit检测到的功能点,我们可以打开我们的ARSCNView:

self.sceneView.debugOptions =

ARSCNDebugOptionShowWorldOrigin |

ARSCNDebugOptionShowFeaturePoints;

我们来检测平面几何,在ARKit中,可以通过设置planeDetection属性来检测水平平面。此值可以设置为ARPlaneDetectionHorizontal或ARPlaneDetectionNone。

- (void)renderer:(id )renderer

didAddNode:(SCNNode *)node

forAnchor:(ARAnchor *)anchor {

SCNNode实例是ARKit创建的一个SceneKit节点,它具有一些类似于方向和位置的属性,然后我们获得一个锚实例,这将告诉我们使用已找到的特定锚点的更多信息,如大小和中心位置的plane。锚实例实际上是一个ARPlaneAnchor类型,比如我们可以得到plane的范围和中心信息。

我们进行渲染plane,可以在虚拟世界中绘制一个SceneKit 3D平面。为此,我们创建一个继承自SCNNode的Plane类。在构造方法中,我们创建平面并相应地调整它的大小:

self.planeGeometry = [SCNPlane planeWithWidth:anchor.extent.x height:anchor.extent.z];

SCNNode *planeNode = [SCNNode nodeWithGeometry:self.planeGeometry];

planeNode.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z);

planeNode.transform = SCNMatrix4MakeRotation(-M_PI / 2.0, 1.0, 0.0, 0.0);

[self addChildNode:planeNode];

现在我们有我们的Plane类,回到ARSCNViewDelegate回调方法中,当ARKit找到一个新的锚点时,我们可以创建我们的新plane:

if (![anchor isKindOfClass:[ARPlaneAnchor class]]) {

return;

Plane *plane = [[Plane alloc] initWithAnchor: (ARPlaneAnchor *)anchor];

[node addChildNode:plane];

更新Plane SceneKit,使得我们在移动时有更稳定的效果。

didUpdateNode:(SCNNode *)node

// See if this is a plane we are currently rendering

Plane *plane = [self.planes objectForKey:anchor.identifier];

if (plane == nil) {

[plane update:(ARPlaneAnchor *)anchor];

更新plane的宽度和高度。

- (void)update:(ARPlaneAnchor *)anchor {

self.planeGeometry.width = anchor.extent.x;

self.planeGeometry.height = anchor.extent.z;

self.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z);

运行,会发现如下一些效果。

添加物理效果

效果预览:

在这个演示中,当用户在屏幕上单击时,我们执行一段代码,这个代码很简单,ARSCNView包含一个hitTest方法,可以通过获得的屏幕坐标点,从相机中心通过该点投射一条射线,并返回结果:

- (void)handleTapFrom: (UITapGestureRecognizer *)recognizer {

CGPoint tapPoint = [recognizer locationInView:self.sceneView];

NSArray *result = [self.sceneView hitTest:tapPoint types:ARHitTestResultTypeExistingPlaneUsingExtent];

if (result.count == 0) {

ARHitTestResult * hitResult = [result firstObject];

[self insertGeometry:hitResult];

通过上述代码,我们可以得到射线与平面交叉点的世界坐标,并在该位置放置一些3D模型等等。

- (void)insertGeometry:(ARHitTestResult *)hitResult {

float dimension = 0.1;

SCNBox *cube = [SCNBox boxWithWidth:dimension

height:dimension

length:dimension

chamferRadius:0];

SCNNode *node = [SCNNode nodeWithGeometry:cube];

node.physicsBody = [SCNPhysicsBody

bodyWithType:SCNPhysicsBodyTypeDynamic

shape:nil];

node.physicsBody.mass = 2.0;

node.physicsBody.categoryBitMask = CollisionCategoryCube;

float insertionYOffset = 0.5;

node.position = SCNVector3Make(

hitResult.worldTransform.columns[3].x,

hitResult.worldTransform.columns[3].y + insertionYOffset,

hitResult.worldTransform.columns[3].z

);

[self.sceneView.scene.rootNode addChildNode:node];

[self.boxes addObject:node];

我们给每个立方体一个physicsBody,它是SceneKit的物理引擎。

接下来,我们实现停止平面检测的功能。用户用两个手指按住屏幕1秒钟,那么我们会隐藏所有的平面并关闭平面检测。

ARWorldTrackingSessionConfiguration *configuration = (ARWorldTrackingSessionConfiguration *)self.sceneView.session.configuration;

configuration.planeDetection = ARPlaneDetectionNone;

[self.sceneView.session runWithConfiguration:configuration];

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

推荐阅读更多精彩内容