iOS11 AR场景中关于3D模型的触碰检测

最新 iOS11中的AR特别火爆,自己也到网上找了几个Demo把玩了下,核心代码无非以下:

//AR视图:展示3D界面

@property(nonatomic,strong)ARSCNView *arSCNView;

添加模型方法一:

// Create a new scene

SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];

// Set the scene to the view

self.arSCNView.scene = scene;

添加模型方法二:

//1.使用场景加载scn文件(scn格式文件是一个基于3D建模的文件,使用3DMax软件可以创建,这里系统有一个默认的3D飞机)--------在右侧我添加了许多3D模型,只需要替换文件名即可

SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];//@"Models.scnassets/chair/chair.scn"];

//2.获取飞机节点(一个场景会有多个节点,此处我们只写,飞机节点则默认是场景子节点的第一个)

//所有的场景有且只有一个根节点,其他所有节点都是根节点的子节点

SCNNode *shipNode = scene.rootNode.childNodes[0];

self.planeNode = shipNode;

//飞机比较大,释放缩放一下并且调整位置让其在屏幕中间

shipNode.scale = SCNVector3Make(0.5, 0.5, 0.5);

shipNode.position = SCNVector3Make(0, -15,-15);

;

//一个飞机的3D建模不是一气呵成的,可能会有很多个子节点拼接,所以里面的子节点也要一起改,否则上面的修改会无效

for (SCNNode *node in shipNode.childNodes) {

node.scale = SCNVector3Make(0.5, 0.5, 0.5);

node.position = SCNVector3Make(0, -15,-15);

}

//3.将飞机节点添加到当前屏幕中

[self.arSCNView.scene.rootNode addChildNode:shipNode];

//环境搭建代码见文后 结尾分割线 下

========================开头分割线====================

  最初想到的当然是通过添加手势看能否凑效,但是如果向ARSCNView添加,有点儿盲目做功,因为ARSCNView上不全是所求的3D模型,不管有没有点击到模型,手势方法都会出发;再观察SCNScene, SCNScene继承自NSObject,观察了API又陷入了死胡同;返回来看ARSCNView有个方法:

/*!

@method hitTest:options:

@abstract Returns an array of SCNHitTestResult for each node that contains a specified point.

@param point A point in the coordinate system of the receiver.

@param options Optional parameters (see the "Hit test options" group for the available options).

*/

- (NSArray<SCNHitTestResult *> *)hitTest:(CGPoint)point options:(nullable NSDictionary<SCNHitTestOption, id> *)options;

该方法会返回一个SCNHitTestResult数组,这个数组中每个元素的node都包含了指定的点(CGPoint)

打个比方:ARSCNView就是个多层合成木板,手指的每次点击,都好像一根针穿透模板,该方法会反回由针穿过的所有点(node)组成的一饿数组,每个点其实都包含了你手指点击的位置(CGPoint),这样我们就可以通过便利每个数组中每个SCNHitTestResult的node,看哪个node有父node,并且找到node的name和3D模型的根节点name做对比,可以找到那就是点击到了3D模型;

代码如下:

SCNNode *vaseNode = scene.rootNode.childNodes[0];

vaseNode.name = @"Virtual object root node";//很重要,就靠name做对比

//4.设置花瓶节点的位置为捕捉到的平地的位置,如果不设置,则默认为原点位置,也就是相机位置

vaseNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z);

//5.将花瓶节点添加到当前屏幕中

//!!!此处一定要注意:花瓶节点是添加到代理捕捉到的节点中,而不是AR试图的根节点。因为捕捉到的平地锚点是一个本地坐标系,而不是世界坐标系

[node addChildNode:vaseNode];

// 系统方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

if (self.arType == ARTypePlane&&self.rootNode) {

self.currentTouches = touches;

UITouch *touch = [self.currentTouches anyObject];

CGPoint tapPoint  = [touch locationInView:self.arSCNView];//该点就是手指的点击位置

NSDictionary *hitTestOptions = [NSDictionary dictionaryWithObjectsAndKeys:@(true),SCNHitTestBoundingBoxOnlyKey, nil];

NSArray<SCNHitTestResult *> * results= [self.arSCNView hitTest:tapPoint options:hitTestOptions];

for (SCNHitTestResult *res in results) {//遍历所有的返回结果中的node

if ([self isNodePartOfVirtualObject:res.node]) {

[self doSomeThing];

break;

}

}

}

}

//上溯找寻指定的node

-(BOOL) isNodePartOfVirtualObject:(SCNNode*)node {

if ([@"Virtual object root node" isEqualToString:node.name]) {

return true;

}

if (node.parentNode != nil) {

return [self isNodePartOfVirtualObject:node.parentNode];

}

return false;

}

===========结尾分割线==============

#pragma mark -搭建ARKit环境

//懒加载会话追踪配置

- (ARSessionConfiguration *)arSessionConfiguration

{

if (_arSessionConfiguration != nil) {

return _arSessionConfiguration;

}

//1.创建世界追踪会话配置(使用ARWorldTrackingSessionConfiguration效果更加好),需要A9芯片支持

ARWorldTrackingSessionConfiguration *configuration = [[ARWorldTrackingSessionConfiguration alloc] init];

//2.设置追踪方向(追踪平面,后面会用到)

configuration.planeDetection = ARPlaneDetectionHorizontal;

_arSessionConfiguration = configuration;

//3.自适应灯光(相机从暗到强光快速过渡效果会平缓一些)

_arSessionConfiguration.lightEstimationEnabled = YES;

return _arSessionConfiguration;

}

//懒加载拍摄会话

- (ARSession *)arSession

{

if(_arSession != nil)

{

return _arSession;

}

//1.创建会话

_arSession = [[ARSession alloc] init];

_arSession.delegate = self;

//2返回会话

return _arSession;

}

//创建AR视图

- (ARSCNView *)arSCNView

{

if (_arSCNView != nil) {

return _arSCNView;

}

//1.创建AR视图

_arSCNView = [[ARSCNView alloc] initWithFrame:self.view.bounds];

//2.设置代理  捕捉到平地会在代理回调中返回

_arSCNView.delegate = self;

//2.设置视图会话

_arSCNView.session = self.arSession;

//3.自动刷新灯光(3D游戏用到,此处可忽略)

_arSCNView.automaticallyUpdatesLighting = YES;

return _arSCNView;

}

- (void)viewDidAppear:(BOOL)animated

{

[super viewDidAppear:animated];

//1.将AR视图添加到当前视图

[self.view addSubview:self.arSCNView];

//2.开启AR会话(此时相机开始工作)

[self.arSession runWithConfiguration:self.arSessionConfiguration];

}

时间: 2024-12-20 03:20:34

iOS11 AR场景中关于3D模型的触碰检测的相关文章

火云开发课堂 - 《Shader从入门到精通》系列 第二十一节:在Shader中对3D模型进行区域遮罩

<Shader从入门到精通>系列在线课程 优惠链接:http://edu.csdn.net/combo/detail/90 第二十一节:在Shader中对3D模型进行区域遮罩 视频地址: http://edu.csdn.net/course/detail/1441/22685?auto_start=1 交流论坛:http://www.firestonegames.com/bbs/forum.php 工程下载地址:请成为正式学员获取工程 课程截图: 版权声明:本文为博主原创文章,未经博主允许不得

火云开发课堂 - 《Shader从入门到精通》系列 第十九节:在Shader中实现3D模型的UV动画

<Shader从入门到精通>系列在线课程 优惠链接:http://edu.csdn.net/combo/detail/90 第十一节:在Shader中实现3D模型的UV动画 视频地址: http://edu.csdn.net/course/detail/1441/22683?auto_start=1 交流论坛:http://www.firestonegames.com/bbs/forum.php 工程下载地址:请成为正式学员获取工程 课程截图: 版权声明:本文为博主原创文章,未经博主允许不得转

火云开发课堂 - 《Shader从入门到精通》系列 第十七节:在Shader中对3D模型进行色彩与纹理色的混合

<Shader从入门到精通>系列在线课程 优惠链接:http://edu.csdn.net/combo/detail/90 第十七节:在Shader中对3D模型进行色彩与纹理色的混合 视频地址: http://edu.csdn.net/course/detail/1441/22681?auto_start=1 交流论坛:http://www.firestonegames.com/bbs/forum.php 工程下载地址:请成为正式学员获取工程 课程截图: 版权声明:本文为博主原创文章,未经博主

火云开发课堂 - 《Shader从入门到精通》系列 第十五节:在Shader中对3D模型进行颜色设置

<Shader从入门到精通>系列在线课程 优惠链接:http://edu.csdn.net/combo/detail/90 第十一节:在Shader中中对3D模型进行颜色设置 视频地址: http://edu.csdn.net/course/detail/1441/22679?auto_start=1 交流论坛:http://www.firestonegames.com/bbs/forum.php 工程下载地址:请成为正式学员获取工程 课程截图: 版权声明:本文为博主原创文章,未经博主允许不得

将.stl文件转化为.dae并动态加载到SceneKit显示(ios中显示3d模型)

ios8之后苹果推出了一个3D模型渲染框架.SceneKit.但是国内针对这方面的教程并不是很多.前两天搞了一下也是一头雾水,终于把最基础的内容搞明白了之后,写下这篇随笔作为cnblogs的开篇,希望能一直写下去. SceneKit现在可以支持有限的几种模型,截止到我写这篇文章为止似乎只有.dae和.abc后一种模型我没有使用过.这篇文章只针对.dae模型写. 首先如果是希望加载一个已有的,不需要程序在运行的时候动态添加的dae模型.那么我们可以直接新建一个game类型的工程.在选项中选择Sce

优化Flash中的3D模型加载

来自:Kid's Zone 最近在做一个公司的Flash3D页游项目,遇到了这个问题,前前后后断断续续也优化了一段时间,觉得还是有必要记录一下一些优化的心得. Flash中加载资源一个最大的问题在于难以使用另外的线程加载资源.诚然Flash有Worker线程,但Worker存在以下几个问题: 1. 使用Worker要求客户的FlashPlayer播放器版本不能过低. 2. 不同Worker之间传递数据手段非常少,缺乏共享内存.使用ByteArray共享数据的话需要先把数据序列化成AMF格式,无论

cocos2d-x在Lua中添加3d模型创建3D动画

--3d模型和3D动画的创建 require"Cocos2d" local Sprite3DScene=class("Sprite3DScene",function() return cc.Scene:create() end) --添加create函数 function Sprite3DScene:create() local scene=Sprite3DScene.new() scene:addChild(scene:init()) return scene e

ANDROID应用中嵌入Unity3D视图(展示3D模型)

效果展示:                 开篇废话: 我现在所在的Team每周需要一个人给大家介绍一个知识点,或者新技术.这礼拜正好轮到我了,由于我工作才一年,面对那帮老鸟讲知识点感觉有点作死.所以我就准备选个新技术介绍一下. 由于我在大学里自学过一段时间Unity3D,所以我想介绍的技术就是它,但我现在做的是应用开发,不能做个小游戏去给大家演示.所以我想到比较简单,直观,而且有可能真正能用到的就是在Android应用中展示3D模型.比如在产品展示时直接把这个产品的3D模型展示出来而不是个图片

HT for Web自定义3D模型的WebGL应用

有不少朋友询问<HTML5 Web 客户端五种离线存储方式汇总>文章例子的3D表计模型是如何生成的,这个例子是通过导入3dmax设计好的表计模型,然后通过obj格式导入到HT for Web系统中进行控制,这种方式特别适合复杂模型的应用场景,但对于监控系统的很多应用其实并不需要专业的美工使用专业的3D编辑工具,完全通过HT for Web预定义的和内置自定义3D模型API就能满足很多应用,这里介绍几种场景的自定义3D模型应用. 上图是采用HT提供的createRingModel函数,通过编辑2