iOS11 AR場景中關於3D模型的觸碰檢測

来源:http://www.cnblogs.com/shuizhuqing/archive/2017/07/12/7158016.html
-Advertisement-
Play Games

最新 iOS11中的AR特別火爆,自己也到網上找了幾個Demo把玩了下,核心代碼無非以下: //AR視圖:展示3D界面 @property(nonatomic,strong)ARSCNView *arSCNView; 添加模型方法一: // Create a new scene SCNScene * ...


      最新 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];

}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 頁面效果 實現步驟 1.引入struts整合json的插件包 2.頁面使用jquery的ajax調用二級聯動的js 3.在Action類中定義findJctUnit()方法,這裡要將返回的List集合放置到棧頂,struts2將其轉換成json數據 struts2的插件包會將壓入到struts2值棧 ...
  • 參數預設值,剩餘參數,拓展參數(default spread rest parameter) 預設參數 let aa=(name='wwrs')= { console.log( ); } aa();//Hello wwrs aa('sss');//Hello sss 擴展參數 let bb=(a,b ...
  • 箭頭函數(arrow function) 基本格式 let say333=()= { console.log("333");//333 } say333(); (name)= { console.log(name); } 調用一個小括弧可以去掉 2個小括弧就不能去掉 name= { console. ...
  • 伺服器推送事件(Server-sent Events)WebSocket 協議的一種伺服器向客戶端發送事件&數據的單向通訊。目前所有主流瀏覽器均支持伺服器發送事件,當然除了 Internet Explorer 。2333... WebSocket 協議是繼HTTP協議後又一伺服器客戶端通訊協議,不同 ...
  • JavaScript URL傳值過程中遇到的問題及知識點總結 Web系統開發過程中經常用到URL進行傳值,剛剛接觸時不太會解析,會出現中文亂碼問題等。 1、父子頁面之間的傳值(在一個頁面中以載入iframe框架的形式調出另一個頁面)。 var URL=“XXXX..?code=aaa&name=li ...
  • 上個周周末,接手了一個移動端的(外包)小項目,一直著手於PC端,對移動端還是一知半解,所以這也是我的一個挑戰,因此,今天心血來潮,總結一些移動端的基礎知識和技巧供自己以後方便查閱,歡迎大家補充或轉載: 一.單位(px,em,rem) 1.px:屏幕設備物理上能顯示出的最小的一個點,不同設備上點的長寬 ...
  • 擴展運算符(Spread operator) let zzz=[2,4,6]; console.log(zzz);//[2, 4, 6] console.log(...zzz);//2 4 6 展開併合並 let a=[1,2,3]; let b=[...a,4,5,6]; console.log( ...
  • 非同步:現在與將來 分塊的程式 可以把JavaScript 程式寫在單獨的js 文件中,這個程式是由多個塊組成的,這些塊 中只有一個是現在執行,其餘在撿來執行,最常見的塊單位是函數。 例如: function now() { return 21; } function later() { answer ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...