ARKit實戰(zhàn):如何實現(xiàn)任意門

ARKit實戰(zhàn):如何實現(xiàn)任意門

相關(guān)

到底有多強?蘋果的增強現(xiàn)實框架:ARKit
ARKit進階:物理世界
ARKit進階:材質(zhì)

技術(shù)

任意門特效的實現(xiàn),主要用到了關(guān)于紋理、材質(zhì)、光照的相關(guān)知識,掌握起來并不困難。
如果對相關(guān)知識不熟悉,可以看一下上面的文章。

github

如果對工程感興趣,可以在github上找到源碼。歡迎star, fork。
github地址:ARKit_trans-dimensional-room

效果

Demo視頻合集
Demo視頻合集有兩段任意門視頻,可以看看效果,分別是:pet_find_transDeminalRoom,
ARKit trans-dimensional room。

目標(biāo)

我們的目標(biāo)是要實現(xiàn)一個獨立的隱藏空間,這個空間只有一個門留給用戶展示,當(dāng)用戶走進去時,可以看到內(nèi)部的細(xì)節(jié)。

思路

先構(gòu)建一個封閉的空間,再用透明材質(zhì)將它包裹起來,當(dāng)用戶進入這個空間后,可以將背景換成全景的圖片,當(dāng)用戶走出時,將背景換回攝像頭數(shù)據(jù)。

實現(xiàn)

實現(xiàn)分三部分:
1 . 處理ARKit檢測到的平面
用于提示可以用于交互的平面,后期模擬物理世界也要用到。

- (void)renderer:(id<SCNSceneRenderer>)renderer didAddNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor{
    if ([anchor isKindOfClass:[ARPlaneAnchor class]] && !_stopDetectPlanes){
        NSLog(@"detected plane");
        [self addPlanesWithAnchor:(ARPlaneAnchor*)anchor forNode:node];
        [self postInfomation:@"touch ground to place room"];
    }
}
- (void)renderer:(id<SCNSceneRenderer>)renderer didUpdateNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor{
    if ([anchor isKindOfClass:[ARPlaneAnchor class]]){
        NSLog(@"updated plane");
        [self updatePlanesForAnchor:(ARPlaneAnchor*)anchor];
    }
}
- (void)renderer:(id<SCNSceneRenderer>)renderer didRemoveNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor{
    if ([anchor isKindOfClass:[ARPlaneAnchor class]]){
        NSLog(@"removed plane");
        [self removePlaneForAnchor:(ARPlaneAnchor*)anchor];
    }
}

2 . 放置transDimenRoom
對于隱藏空間,抽象成兩個類來表達:transDimenRoomtransDimenStruct
后者用于提供一些平板等基礎(chǔ)結(jié)構(gòu),前者將這些結(jié)構(gòu)拼成一個房間,留一個門框出來讓用戶能夠看見里面。
當(dāng)需要放置任意門時,就用+transDimenRoomAtPosition:方法創(chuàng)建一個transDimenRoom,當(dāng)用戶走進去時,用-hideWalls:隱藏四周的墻壁,切換成全景背景。

@interface transDimenRoom : SCNNode
@property (nonatomic, strong) SCNNode *walls;

+(instancetype)transDimenRoomAtPosition:(SCNVector3)position;
//TODO:check  if user in room
-(BOOL)checkIfInRoom:(SCNVector3)position;

-(void)hideWalls:(BOOL)hidden;
@end

3 . 檢測到用戶走進房間
目前為了簡單起見,是判斷用戶與房間中心的距離,當(dāng)距離小于1時,就認(rèn)為用戶進入了房間。
這里的邏輯以后會收歸到transDimenRoom中。

- (void)renderer:(id<SCNSceneRenderer>)renderer updateAtTime:(NSTimeInterval)time{
    if (_room.presentationNode) {
        
        SCNVector3 position = self.sceneView.pointOfView.presentationNode.worldPosition;
        
        SCNVector3 roomCenter = _room.walls.worldPosition;
        
        CGFloat distance = GLKVector3Length(GLKVector3Make(position.x - roomCenter.x, 0, position.z - roomCenter.z));
        
        if (distance < 1){
            NSLog(@"In room");
            [self handleUserInRoom:YES];
            return;
        }
        
        [self handleUserInRoom:NO];
        
    }
}

展望

工程大致提供了讓用戶從真實世界進入虛擬空間的力能,目前功能還有一些問題需要改進:

  1. 進入房間后,用skyBox代替背景,會看不到門后的真實世界,考慮用shader去渲染門的內(nèi)容
  2. 判斷用戶進入房間的方法比較粗糙
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容