日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ARKit从入门到精通(9)-ARKit让飞机跟着镜头飞起来

發(fā)布時間:2024/9/30 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ARKit从入门到精通(9)-ARKit让飞机跟着镜头飞起来 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • 轉(zhuǎn)載請注明出處:ARKit從入門到精通(9)-ARKit讓飛機跟著鏡頭飛起來

  • 1.1-ARKit物體跟隨相機移動流程介紹

  • 1.2-完整代碼
  • 1.3-代碼下載地址
  • 廢話不多說,先看效果

1001.gif

1.1-ARKit物體跟隨相機移動流程介紹

  • 1.點擊屏幕添加物體,已經(jīng)在第三小節(jié)ARKit從入門到精通(3)-ARKit自定義實現(xiàn)中介紹

  • 2.監(jiān)聽ARSession的代理

    • 相機的移動是由AR會話來監(jiān)聽的
  • 3.在ARSession的相機移動代理中獲取相機的當前位置,修改物體的位置與相機位置一致,即可實現(xiàn)物體跟隨相機移動而移動

  • 核心代碼介紹
#pragma mark -ARSessionDelegate//會話位置更新(監(jiān)聽相機的移動),此代理方法會調(diào)用非常頻繁,只要相機移動就會調(diào)用,如果相機移動過快,會有一定的誤差,具體的需要強大的算法去優(yōu)化,筆者這里就不深入了 - (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame {NSLog(@"相機移動");if (self.arType != ARTypeMove) {return;}//移動飛機if (self.planeNode) {//捕捉相機的位置,讓節(jié)點隨著相機移動而移動//根據(jù)官方文檔記錄,相機的位置參數(shù)在4X4矩陣的第三列self.planeNode.position =SCNVector3Make(frame.camera.transform.columns[3].x,frame.camera.transform.columns[3].y,frame.camera.transform.columns[3].z);}}

1.2-完整代碼

#import "ARSCNViewViewController.h"//3D游戲框架 #import <SceneKit/SceneKit.h> //ARKit框架 #import <ARKit/ARKit.h>@interface ARSCNViewViewController ()<ARSCNViewDelegate,ARSessionDelegate>//AR視圖:展示3D界面 @property(nonatomic,strong)ARSCNView *arSCNView;//AR會話,負責管理相機追蹤配置及3D相機坐標 @property(nonatomic,strong)ARSession *arSession;//會話追蹤配置:負責追蹤相機的運動 @property(nonatomic,strong)ARSessionConfiguration *arSessionConfiguration;//飛機3D模型(本小節(jié)加載多個模型) @property(nonatomic,strong)SCNNode *planeNode;@end@implementation ARSCNViewViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view. }- (void)back:(UIButton *)btn {[self dismissViewControllerAnimated:YES completion:nil]; }- (void)viewDidAppear:(BOOL)animated {[super viewDidAppear:animated];//1.將AR視圖添加到當前視圖[self.view addSubview:self.arSCNView];//2.開啟AR會話(此時相機開始工作)[self.arSession runWithConfiguration:self.arSessionConfiguration];//添加返回按鈕UIButton *btn = [UIButton buttonWithType: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 = [UIColor greenColor];[btn addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];[self.view addSubview:btn];}#pragma mark- 點擊屏幕添加飛機 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {if (self.arType == ARTypePlane || self.planeNode != nil) {return;}//1.使用場景加載scn文件(scn格式文件是一個基于3D建模的文件,使用3DMax軟件可以創(chuàng)建,這里系統(tǒng)有一個默認的3D飛機)--------在右側(cè)我添加了許多3D模型,只需要替換文件名即可SCNScene *scene = [SCNScene sceneNamed:@"Models.scnassets/ship.scn"];//2.獲取飛機節(jié)點(一個場景會有多個節(jié)點,此處我們只寫,飛機節(jié)點則默認是場景子節(jié)點的第一個)//所有的場景有且只有一個根節(jié)點,其他所有節(jié)點都是根節(jié)點的子節(jié)點SCNNode *shipNode = scene.rootNode.childNodes[0];self.planeNode = shipNode;//飛機比較大,釋放縮放一下并且調(diào)整位置讓其在屏幕中間shipNode.scale = SCNVector3Make(0.5, 0.5, 0.5);shipNode.position = SCNVector3Make(0, -15,-15);;//一個飛機的3D建模不是一氣呵成的,可能會有很多個子節(jié)點拼接,所以里面的子節(jié)點也要一起改,否則上面的修改會無效for (SCNNode *node in shipNode.childNodes) {node.scale = SCNVector3Make(0.5, 0.5, 0.5);node.position = SCNVector3Make(0, -15,-15);}//3.將飛機節(jié)點添加到當前屏幕中[self.arSCNView.scene.rootNode addChildNode:shipNode];}#pragma mark -搭建ARKit環(huán)境//懶加載會話追蹤配置 - (ARSessionConfiguration *)arSessionConfiguration {if (_arSessionConfiguration != nil) {return _arSessionConfiguration;}//1.創(chuàng)建世界追蹤會話配置(使用ARWorldTrackingSessionConfiguration效果更加好),需要A9芯片支持ARWorldTrackingSessionConfiguration *configuration = [[ARWorldTrackingSessionConfiguration alloc] init];//2.設(shè)置追蹤方向(追蹤平面,后面會用到)configuration.planeDetection = ARPlaneDetectionHorizontal;_arSessionConfiguration = configuration;//3.自適應燈光(相機從暗到強光快速過渡效果會平緩一些)_arSessionConfiguration.lightEstimationEnabled = YES;return _arSessionConfiguration;}//懶加載拍攝會話 - (ARSession *)arSession {if(_arSession != nil){return _arSession;}//1.創(chuàng)建會話_arSession = [[ARSession alloc] init];_arSession.delegate = self;//2返回會話return _arSession; }//創(chuàng)建AR視圖 - (ARSCNView *)arSCNView {if (_arSCNView != nil) {return _arSCNView;}//1.創(chuàng)建AR視圖_arSCNView = [[ARSCNView alloc] initWithFrame:self.view.bounds];//2.設(shè)置代理 捕捉到平地會在代理回調(diào)中返回_arSCNView.delegate = self;//2.設(shè)置視圖會話_arSCNView.session = self.arSession;//3.自動刷新燈光(3D游戲用到,此處可忽略)_arSCNView.automaticallyUpdatesLighting = YES;return _arSCNView; }#pragma mark -- ARSCNViewDelegate//添加節(jié)點時候調(diào)用(當開啟平地捕捉模式之后,如果捕捉到平地,ARKit會自動添加一個平地節(jié)點) - (void)renderer:(id <SCNSceneRenderer>)renderer didAddNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {if(self.arType != ARTypePlane){return;}if ([anchor isMemberOfClass:[ARPlaneAnchor class]]) {NSLog(@"捕捉到平地");//添加一個3D平面模型,ARKit只有捕捉能力,錨點只是一個空間位置,要想更加清楚看到這個空間,我們需要給空間添加一個平地的3D模型來渲染他//1.獲取捕捉到的平地錨點ARPlaneAnchor *planeAnchor = (ARPlaneAnchor *)anchor;//2.創(chuàng)建一個3D物體模型 (系統(tǒng)捕捉到的平地是一個不規(guī)則大小的長方形,這里筆者將其變成一個長方形,并且是否對平地做了一個縮放效果)//參數(shù)分別是長寬高和圓角SCNBox *plane = [SCNBox boxWithWidth:planeAnchor.extent.x*0.3 height:0 length:planeAnchor.extent.x*0.3 chamferRadius:0];//3.使用Material渲染3D模型(默認模型是白色的,這里筆者改成紅色)plane.firstMaterial.diffuse.contents = [UIColor redColor];//4.創(chuàng)建一個基于3D物體模型的節(jié)點SCNNode *planeNode = [SCNNode nodeWithGeometry:plane];//5.設(shè)置節(jié)點的位置為捕捉到的平地的錨點的中心位置 SceneKit框架中節(jié)點的位置position是一個基于3D坐標系的矢量坐標SCNVector3MakeplaneNode.position =SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z);//self.planeNode = planeNode;[node addChildNode:planeNode];//2.當捕捉到平地時,2s之后開始在平地上添加一個3D模型dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{//1.創(chuàng)建一個花瓶場景SCNScene *scene = [SCNScene sceneNamed:@"Models.scnassets/vase/vase.scn"];//2.獲取花瓶節(jié)點(一個場景會有多個節(jié)點,此處我們只寫,花瓶節(jié)點則默認是場景子節(jié)點的第一個)//所有的場景有且只有一個根節(jié)點,其他所有節(jié)點都是根節(jié)點的子節(jié)點SCNNode *vaseNode = scene.rootNode.childNodes[0];//4.設(shè)置花瓶節(jié)點的位置為捕捉到的平地的位置,如果不設(shè)置,則默認為原點位置,也就是相機位置vaseNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z);//5.將花瓶節(jié)點添加到當前屏幕中//!!!此處一定要注意:花瓶節(jié)點是添加到代理捕捉到的節(jié)點中,而不是AR試圖的根節(jié)點。因為捕捉到的平地錨點是一個本地坐標系,而不是世界坐標系[node addChildNode:vaseNode];});} }//刷新時調(diào)用 - (void)renderer:(id <SCNSceneRenderer>)renderer willUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {NSLog(@"刷新中"); }//更新節(jié)點時調(diào)用 - (void)renderer:(id <SCNSceneRenderer>)renderer didUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {NSLog(@"節(jié)點更新");}//移除節(jié)點時調(diào)用 - (void)renderer:(id <SCNSceneRenderer>)renderer didRemoveNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {NSLog(@"節(jié)點移除"); }#pragma mark -ARSessionDelegate//會話位置更新(監(jiān)聽相機的移動),此代理方法會調(diào)用非常頻繁,只要相機移動就會調(diào)用,如果相機移動過快,會有一定的誤差,具體的需要強大的算法去優(yōu)化,筆者這里就不深入了 - (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame {NSLog(@"相機移動");if (self.arType != ARTypeMove) {return;}//移動飛機if (self.planeNode) {//捕捉相機的位置,讓節(jié)點隨著相機移動而移動//根據(jù)官方文檔記錄,相機的位置參數(shù)在4X4矩陣的第三列self.planeNode.position =SCNVector3Make(frame.camera.transform.columns[3].x,frame.camera.transform.columns[3].y,frame.camera.transform.columns[3].z);}} - (void)session:(ARSession *)session didAddAnchors:(NSArray<ARAnchor*>*)anchors {NSLog(@"添加錨點");}- (void)session:(ARSession *)session didUpdateAnchors:(NSArray<ARAnchor*>*)anchors {NSLog(@"刷新錨點");}- (void)session:(ARSession *)session didRemoveAnchors:(NSArray<ARAnchor*>*)anchors {NSLog(@"移除錨點");}- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];// 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. } */@end

1.3-代碼下載地址

  • ARKit從入門到精通Demo:http://download.csdn.net/detail/u013263917/9868679

  • 筆者已經(jīng)將8、9、10三小節(jié)的代碼合并成一個完整的小demo,供讀者交流學習


總結(jié)

以上是生活随笔為你收集整理的ARKit从入门到精通(9)-ARKit让飞机跟着镜头飞起来的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。