ARKit進階:物理世界

相關(guān)

到底有多強器躏?蘋果的增強現(xiàn)實框架:ARKit
ARKit進階:材質(zhì)
ARKit實戰(zhàn):如何實現(xiàn)任意門

寫在前面

ARKit的渲染能力是由其他框架實現(xiàn)的箩兽,除了蘋果的SceneKit, Unity3D、UE, 或者其他自定義的OpenGL、Metal渲染引擎都可以與ARKit相結(jié)合。本文所介紹的技術(shù)都是基于SceneKit。

Demo

這個Demo使用蘋果的demo改的湖苞,視頻鏈接

Demo

關(guān)于物理模擬

雖然物理引擎都具有真實的物理變量详囤,如質(zhì)量财骨、重力、摩擦力等,但當(dāng)我們說道物理模擬隆箩,不是要真的去用真實世界的數(shù)值去模擬物理行為该贾,事實上那樣反而會失真。我們要做的是維護好各種變量的相對關(guān)系摘仅,制造一種真實的物理感官即可靶庙。

SCNPhysicsWorld

游戲中的物理引擎用來模擬3D世界中的物理特效,使物體具備的真實的動態(tài)行為娃属。SceneKit使用SCNPhysicsWorld來管理這種物理模擬六荒,讓物體的碰撞、連接矾端、掉落等具有真實感掏击。
ARSCNScene具有繼承自SCNScene的默認SCNPhysicsWorld。任何添加到ARSCNScene的物理對象秩铆,都會注冊到SCNPhysicsWorld中砚亭,維護其中的物理關(guān)系是重點。
利用SCNPhysicsWorld殴玛,我們主要做以下工作:

  • 管理全局的物理變量捅膘。
  • 利用其代理方法觀察物理行為。
  • 使用contact/ray/convex test方法滚粟,檢測物理之間的物理關(guān)系寻仗。

SCNPhysicsBody

想要一個SCNNode參與到物理模擬中,只需要給node.physicsBody賦值一個合適的值凡壤。
所有擁有physics body的node署尤,會在render loop的physics simulation階段,計算該node的物理行為亚侠,在接下來的渲染階段對node做相應(yīng)的變換曹体。

sceneKit render loop

一個合適的SCNPhysicsBody需要合理設(shè)置其typephysicsShape
type:

  • dynamic: 可以被碰撞硝烂、力影響箕别。適合場景中物理引擎可以完全接管的類型,如掉落的石塊钢坦。
  • static: 不受碰撞究孕、力影響,且不能移動爹凹。適合場景中地面厨诸、墻體等。
  • kinematic: 不受碰撞禾酱、力影響微酬,但移動的時候會影響其他body绘趋。適合場景中的角色,畢竟我們不想角色的移動不想被太多力影響颗管。

physicsShape:
當(dāng)physics body參與到物理模擬時陷遮,一個更貼合的形狀能得到一個更令人滿意的結(jié)果。但是對于一個比較復(fù)雜的幾何體垦江,簡單的convex會顯得過大帽馋,concave又會太復(fù)雜影響性能。這種情況可以使用若干個簡單的形狀拼裝一個相似的形狀比吭,或者由設(shè)計給出一個合理的形狀绽族,總之形狀的選擇要平衡性能與真實感。

body category

一個場景中會有許多node衩藤,需要給他們設(shè)置category吧慢,讓我們只關(guān)注感興趣的碰撞、接觸赏表。尤其要注意的是它們各自的默認值检诗,不然很容易出現(xiàn)bug。
categoryBitMask:
指定body的類型瓢剿, dynamic/kinematic body默認為1逢慌,static body默認為2。
collisionBitMask:
指定能與該body產(chǎn)生碰撞的physics body類型间狂。默認是-1涕癣,即每位都置1。
contactTestBitMask:
指定哪種類型的physics body與該body發(fā)生接觸(幾何體交叉)后前标,通知給physics world。
這個屬性在OSX10.11和iOS9以上默認值是0距潘,以下與collisionBitMask相同炼列。

記住重設(shè)physics body時,要恢復(fù)這些值

注意SCNNode也有一個categoryBitMask音比,用法與這個類似俭尖。但在scene test時,這兩個容易搞混洞翩。這里吐槽以下蘋果的命名稽犁。

SCNPhysicsShape

當(dāng)物理引擎檢測碰撞時,使用的是SCNPhysicsShape來計算結(jié)果骚亿,除了性能已亥,我碰到兩個關(guān)于physicsShape的問題:

  1. 如果node.geometry是不可見的,那個雖然它有physics shape来屠,在調(diào)試時也會顯示虑椎,但不會參與物理模擬震鹉。
  2. SceneKit的物理引擎是不支持縮放變換的。如果一個node做縮放變換后捆姜,physics body將仍是原來的尺寸传趾。這種情況看我的回答,重點是當(dāng)attach body之前如果沒有指定形狀泥技,那么SceneKit才會使用scale信息浆兰,使用SCNPhysicsShapeScaleKey也有一樣的效果。
//still has identity scale
SCNPhysicsBody *body = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic shape:[SCNPhysicsShape shapeWithGeometry:ramp.geometry options:nil]];
//this did worked
SCNPhysicsBody *body = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic                                                     shape:nil];

SceneKit automatically creates a physics shape for the body when you attach it to a node, based on that node’s geometry property

物理模擬與其他動畫的沖突

從SceneKit的render loop可以看到珊豹,物理模擬實際上也是一種動畫簸呈,只不過動畫的參數(shù)由物理引擎控制。SceneKit也遵循iOS的傳統(tǒng)平夜,具有隱式蝶棋、顯式動畫,同時有SCNAction接口忽妒。由于物理引擎
是將所有的計算結(jié)果應(yīng)用到動畫層上玩裙,即node.presentationNode,這會讓新加入的動畫顯得不正常段直。因為其他動畫的初始值是從node.transform中讀取的吃溅。對于這種問題,需要讀出node.presentationNode.transform的值用于動畫的初始值鸯檬。

process of collision

對于簡單的碰撞决侈,只要設(shè)置好physics body和category bit mask,collision bit mask等參數(shù)喧务,其他的就由物理引擎接管了赖歌。
碰撞的處理過程由3個部分組成。

collision detection

物理引擎會在渲染時檢測物體之間的physics body是否發(fā)生重疊功茴,這一過程我們可以通過<SCNPhysicsContactDelegate>中的方法觀察庐冯。

collision determination

與操作兩個物體的之間的categoryBitMask和collisionBitMask,若返回非0坎穿,則發(fā)生碰撞展父。

collision respond

物理引擎會在渲染之前,計算物理碰撞的結(jié)果并應(yīng)用到物體上玲昧。

contact test

當(dāng)有兩個物體相接觸栖茉,若categoryBitMaskcontactTestBitMask相與不為零,那么會調(diào)用<SCNPhysicsContactDelegate>的方法孵延。很顯然這個結(jié)果的集合是小于碰撞結(jié)果的吕漂。通過這個方法,我們能夠控制兩個物體之間的碰撞隙袁,這在物理引擎接管的碰撞動畫不理想時痰娱,是非常有用的弃榨。
當(dāng)接觸發(fā)生時,代理方法會傳來SCNPhysicsContact對象梨睁,它包含了接觸的對象鲸睛、部位、法線與重疊距離坡贺。通過它可以修正錯誤的動畫官辈。例如我將一個石塊從高處墜落,如果速度特別大遍坟,那么它會直接穿過底部的平面拳亿。因為在render loop的渲染時,兩者相接觸的那一幀在物理模擬時愿伴,石塊已經(jīng)大部分穿過了平面肺魁,這樣在下一幀石塊會直接穿過去,而不是回彈隔节《炀可以看我的回答

scene test

SceneKit與ARKit中共有以下幾種scene test怎诫,用以觀察世界中的物體關(guān)系瘾晃,作用類似UIKit的 hitTest: 方法。

AR scene test

//ARSCNView
- (NSArray<ARHitTestResult *> *)hitTest:(CGPoint)point 
                                  types:(ARHitTestResultType)types;

根據(jù)ARSCNView中的點幻妓,構(gòu)造一條3D世界的射線蹦误,搜索ARAnchor或真實物體(特征點或已檢測出的平面)。
scene test

//SCNSceneRenderer
- (NSArray<SCNHitTestResult *> *)hitTest:(CGPoint)point 
                                 options:(NSDictionary<SCNHitTestOption, id> 
                                 
//SCNNode
- (NSArray<SCNHitTestResult *> *)hitTestWithSegmentFromPoint:(SCNVector3)pointA 
                                                     toPoint:(SCNVector3)pointB 
                                                     options:(NSDictionary<NSString *,id> *)options;

第一個方法:根據(jù)SCNSceneRenderer(SCNView等)中的點肉津,構(gòu)造一條3D世界的射線强胰,搜索與射線相交的幾何體,node.geometry為nil則忽視妹沙。
第二個方法:在目標node的局部空間中哪廓,搜索與pointA-pointB線段相交的子node。

physics body test

//SCNPhysicsBody
- (NSArray<SCNHitTestResult *> *)rayTestWithSegmentFromPoint:(SCNVector3)origin 
                                                     toPoint:(SCNVector3)dest 
                                                     options:(NSDictionary<SCNPhysicsTestOption, id> *)options;
- (NSArray<SCNPhysicsContact *> *)convexSweepTestWithShape:(SCNPhysicsShape *)shape 
                                             fromTransform:(SCNMatrix4)from 
                                               toTransform:(SCNMatrix4)to 
                                                   options:(NSDictionary<SCNPhysicsTestOption, id> *)options;

第一個方法:在物理世界中初烘,返回在兩點之間的physics body所屬的node。
第二個方法:在物理世界中分俯,按form-to變換滑動指定的形狀肾筐,返回相交的physics body所屬的node。

contact test

//contact test
- (NSArray<SCNPhysicsContact *> *)contactTestBetweenBody:(SCNPhysicsBody *)bodyA 
                                                 andBody:(SCNPhysicsBody *)bodyB 
                                                 options:(NSDictionary<SCNPhysicsTestOption, id> *)options;
- (NSArray<SCNPhysicsContact *> *)contactTestWithBody:(SCNPhysicsBody *)body 
                                              options:(NSDictionary<SCNPhysicsTestOption, id> *)options;

第一個方法:檢測物理世界中缸剪,兩個body是否發(fā)生接觸吗铐,返回所有的接觸點。
第二個方法:返回所有在物理世界中與指定body發(fā)生contact的node杏节。

最后

物理引擎能夠幫助我們模擬真實世界的效果唬渗,雖然高級的特效一般都是自己在渲染循環(huán)中實現(xiàn)的典阵,但它大大減輕了我們計算成本。擁有良好的物理特效镊逝,能夠讓用戶有真實的感受壮啊,希望本篇文章能夠幫助大家。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撑蒜,一起剝皮案震驚了整個濱河市歹啼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌座菠,老刑警劉巖狸眼,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浴滴,居然都是意外死亡拓萌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門升略,熙熙樓的掌柜王于貴愁眉苦臉地迎上來微王,“玉大人,你說我怎么就攤上這事降宅÷钤叮” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵腰根,是天一觀的道長激才。 經(jīng)常有香客問我,道長额嘿,這世上最難降的妖魔是什么瘸恼? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮册养,結(jié)果婚禮上东帅,老公的妹妹穿的比我還像新娘。我一直安慰自己球拦,他們只是感情好靠闭,可當(dāng)我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坎炼,像睡著了一般愧膀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谣光,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天檩淋,我揣著相機與錄音,去河邊找鬼萄金。 笑死蟀悦,一個胖子當(dāng)著我的面吹牛媚朦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播日戈,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼询张,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涎拉?” 一聲冷哼從身側(cè)響起瑞侮,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鼓拧,沒想到半個月后半火,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡季俩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年钮糖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酌住。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡店归,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酪我,到底是詐尸還是另有隱情消痛,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布都哭,位于F島的核電站秩伞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏欺矫。R本人自食惡果不足惜纱新,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望穆趴。 院中可真熱鬧脸爱,春花似錦、人聲如沸未妹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽络它。三九已至捏鱼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間酪耕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工轨淌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迂烁,地道東北人看尼。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像盟步,于是被迫代替她去往敵國和親藏斩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,860評論 2 361

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

  • 111. [動畫系統(tǒng)]如何將其他類型的動畫轉(zhuǎn)換成關(guān)鍵幀動畫却盘? 動畫->點緩存->關(guān)鍵幀 112. [動畫]Unit...
    胤醚貔貅閱讀 13,065評論 3 90
  • 更新:【面試題含答案】http://bbs.9ria.com/thread-288394-1-1.html 高頻問...
    好怕怕閱讀 4,757評論 3 52
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫狰域、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,124評論 4 61
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理黄橘,服務(wù)發(fā)現(xiàn)兆览,斷路器,智...
    卡卡羅2017閱讀 134,715評論 18 139
  • 吃貨句
    榮姑娘呀閱讀 217評論 0 0