ARKit让飞机跟着镜头飞起来2(转)

其实是会一直围着你转圈的,只不过笔者不好意思暴露家里的场景,所以请读者朋友们见谅~

1101.gif

1.1-ARKit物体围绕相机旋转流程介绍

1.点击屏幕添加物体,已经在第三小节ARKit从入门到精通(3)-ARKit自定义实现中介绍

2.实现物体的围绕相机旋转(这里主要会用到SceneKit框架中内容)

注意:绕相机旋转的关键点在于:在相机的位置创建一个空节点,然后将台灯添加到这个空节点,最后让这个空节点自身旋转,就可以实现台灯围绕相机旋转

1.为什么要在相机的位置创建一个空节点呢?因为你不可能让相机也旋转

2.为什么不直接让台灯旋转呢? 这样的话只能实现台灯的自转,而不能实现公转

核心代码介绍

#pragma mark- 点击屏幕添加飞机- (void)touchesBegan

NSSet*)touches withEvent

UIEvent*)event{    [self.planeNode removeFromParentNode];//1.使用场景加载scn文件(scn格式文件是一个基于3D建模的文件,使用3DMax软件可以创建,这里系统有一个默认的3D飞机)--------在右侧我添加了许多3D模型,只需要替换文件名即可SCNScene*scene = [SCNScenesceneNamed:@"Models.scnassets/lamp/lamp.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*nodeinshipNode.childNodes) {        node.scale =SCNVector3Make(0.5,0.5,0.5);        node.position =SCNVector3Make(0,-15,-15);    }self.planeNode.position =SCNVector3Make(0,0,-20);//3.绕相机旋转//绕相机旋转的关键点在于:在相机的位置创建一个空节点,然后将台灯添加到这个空节点,最后让这个空节点自身旋转,就可以实现台灯围绕相机旋转//1.为什么要在相机的位置创建一个空节点呢?因为你不可能让相机也旋转//2.为什么不直接让台灯旋转呢? 这样的话只能实现台灯的自转,而不能实现公转SCNNode*node1 = [[SCNNodealloc] init];//空节点位置与相机节点位置一致node1.position =self.arSCNView.scene.rootNode.position;//将空节点添加到相机的根节点[self.arSCNView.scene.rootNode addChildNode:node1];// !!!将台灯节点作为空节点的子节点,如果不这样,那么你将看到的是台灯自己在转,而不是围着你转[node1 addChildNode:self.planeNode];//旋转核心动画CABasicAnimation*moonRotationAnimation = [CABasicAnimationanimationWithKeyPath:@"rotation"];//旋转周期moonRotationAnimation.duration =30;//围绕Y轴旋转360度  (不明白ARKit坐标系的可以看笔者之前的文章)moonRotationAnimation.toValue = [NSValuevalueWithSCNVector4:SCNVector4Make(0,1,0, M_PI *2)];//无限旋转  重复次数为无穷大moonRotationAnimation.repeatCount = FLT_MAX;//开始旋转  !!!:切记这里是让空节点旋转,而不是台灯节点。  理由同上[node1 addAnimation:moonRotationAnimation forKey:@"moon rotation around earth"];}

1.2-完整代码

#import "ARSCNViewViewController.h"//3D游戏框架#import

//ARKit框架#import@interface ARSCNViewViewController ()//AR视图:展示3D界面@property(nonatomic,strong)ARSCNView *arSCNView;//AR会话,负责管理相机追踪配置及3D相机坐标@property(nonatomic,strong)ARSession *arSession;//会话追踪配置:负责追踪相机的运动@property(nonatomic,strong)ARSessionConfiguration *arSessionConfiguration;//飞机3D模型(本小节加载多个模型)@property(nonatomic,strong)SCNNode*planeNode;@end@implementation ARSCNViewViewController- (void)viewDidLoad {    [superviewDidLoad];// Do any additional setup after loading the view.}- (void)back

UIButton*)btn{    [selfdismissViewControllerAnimated:YES completion:nil];}- (void)viewDidAppear

BOOL)animated{    [superviewDidAppear:animated];//1.将AR视图添加到当前视图[self.view addSubview:self.arSCNView];//2.开启AR会话(此时相机开始工作)[self.arSession runWithConfiguration:self.arSessionConfiguration];//添加返回按钮UIButton*btn = [UIButtonbuttonWithType:UIButtonTypeCustom];    [btn setTitle:@"返回"forState:UIControlStateNormal];    btn.frame =CGRectMake(self.view.bounds.size.width/2-50,self.view.bounds.size.height-100,100,50);    btn.backgroundColor = [UIColorgreenColor];    [btn addTarget:selfaction:@selector(back

forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:btn];}#pragma mark- 点击屏幕添加飞机- (void)touchesBegan

NSSet

*)touches withEvent

UIEvent*)event{    [self.planeNode removeFromParentNode];//1.使用场景加载scn文件(scn格式文件是一个基于3D建模的文件,使用3DMax软件可以创建,这里系统有一个默认的3D飞机)--------在右侧我添加了许多3D模型,只需要替换文件名即可SCNScene*scene = [SCNScenesceneNamed:@"Models.scnassets/lamp/lamp.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*nodeinshipNode.childNodes) {        node.scale =SCNVector3Make(0.5,0.5,0.5);        node.position =SCNVector3Make(0,-15,-15);    }self.planeNode.position =SCNVector3Make(0,0,-20);//3.绕相机旋转//绕相机旋转的关键点在于:在相机的位置创建一个空节点,然后将台灯添加到这个空节点,最后让这个空节点自身旋转,就可以实现台灯围绕相机旋转//1.为什么要在相机的位置创建一个空节点呢?因为你不可能让相机也旋转//2.为什么不直接让台灯旋转呢? 这样的话只能实现台灯的自转,而不能实现公转SCNNode*node1 = [[SCNNodealloc] init];//空节点位置与相机节点位置一致node1.position =self.arSCNView.scene.rootNode.position;//将空节点添加到相机的根节点[self.arSCNView.scene.rootNode addChildNode:node1];// !!!将台灯节点作为空节点的子节点,如果不这样,那么你将看到的是台灯自己在转,而不是围着你转[node1 addChildNode:self.planeNode];//旋转核心动画CABasicAnimation*moonRotationAnimation = [CABasicAnimationanimationWithKeyPath:@"rotation"];//旋转周期moonRotationAnimation.duration =30;//围绕Y轴旋转360度  (不明白ARKit坐标系的可以看笔者之前的文章)moonRotationAnimation.toValue = [NSValuevalueWithSCNVector4:SCNVector4Make(0,1,0, M_PI *2)];//无限旋转  重复次数为无穷大moonRotationAnimation.repeatCount = FLT_MAX;//开始旋转  !!!:切记这里是让空节点旋转,而不是台灯节点。  理由同上[node1 addAnimation:moonRotationAnimation forKey:@"moon rotation around earth"];}#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;}#pragma mark -- ARSCNViewDelegate//添加节点时候调用(当开启平地捕捉模式之后,如果捕捉到平地,ARKit会自动添加一个平地节点)- (void)renderer

id

)renderer didAddNode

SCNNode*)node forAnchor

ARAnchor *)anchor{}//刷新时调用- (void)renderer

id

)renderer willUpdateNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor{NSLog(@"刷新中");}//更新节点时调用- (void)renderer:(id)renderer didUpdateNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor{NSLog(@"节点更新");}//移除节点时调用- (void)renderer:(id)renderer didRemoveNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor{NSLog(@"节点移除");}#pragma mark -ARSessionDelegate//会话位置更新(监听相机的移动),此代理方法会调用非常频繁,只要相机移动就会调用,如果相机移动过快,会有一定的误差,具体的需要强大的算法去优化,笔者这里就不深入了- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame{NSLog(@"相机移动");}- (void)session:(ARSession *)session didAddAnchors:(NSArray*)anchors{NSLog(@"添加锚点");}- (void)session:(ARSession *)session didUpdateAnchors:(NSArray*)anchors{NSLog(@"刷新锚点");}- (void)session:(ARSession *)session didRemoveAnchors:(NSArray*)anchors{NSLog(@"移除锚点");}- (void)didReceiveMemoryWarning {    [superdidReceiveMemoryWarning];// Dispose of any resources that can be recreated.}/*#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {    // Get the new view controller using [segue destinationViewController].    // Pass the selected object to the new view controller.}*/@end1.3-代码下载地址

ARKit从入门到精通Demo:http://download.csdn.net/detail/u013263917/9868679

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

推荐阅读更多精彩内容