以前玩了下vuforia的視頻播放轻要,太酷了!它的視頻播放是基于上傳的目標(biāo)上面播放旱爆,移動(dòng)目標(biāo)舀射,視頻也會(huì)跟著移動(dòng)。但是今天我們要研究的是基于ARKit播放視頻怀伦,因?yàn)锳RKit目前只支持橫向平面脆烟,所以我們的視頻就在ARKit檢測(cè)到的平面上面播放視頻。
先來看下效果:
提供播放環(huán)境
因?yàn)槲覀冞@次視頻是基于檢測(cè)到的平面播放房待,那我們就把視頻渲染到展示出來的模型上面邢羔。該模型可以自己創(chuàng)建一個(gè)scn文件創(chuàng)建一個(gè)顯示屏形狀的模型,這里我就用別人創(chuàng)建好的顯示屏模型桑孩。
開始寫代碼
這里我就不貼出ARKit的初始化配置以及怎么展示模型的代碼了张抄,該部分盡量少廢話,直接上最核心的東西:渲染視頻洼怔。
首先我們要?jiǎng)?chuàng)建一個(gè)TV對(duì)象,繼承自SCNNode:
@interface TVNode : SCNNode
@property(nonatomic, strong, readonly) AVPlayer *player;
@property (nonatomic, strong) SCNNode *tvNode;
@property (nonatomic, strong) SCNNode *videoRendererNode;
- (void)updateVideoNodeWithPlayer:(AVPlayer *)player;
@end
該TV對(duì)象包含一個(gè)AVPlayer的屬性左驾,用于播放視頻镣隶,同時(shí)它還包含兩個(gè)SCNNode類型的屬性,tvNode是場(chǎng)景中的顯示屏模型對(duì)象诡右,videoRendererNode是播放視頻的對(duì)象安岂,videoRendererNode作為tvNode的子節(jié)點(diǎn),其實(shí)tvNode就是給videoRendererNode提供大小和位置(播放環(huán)境)帆吻。
updateVideoNodeWithPlayer: 改方法更新播放視頻
首先我們創(chuàng)建tvNode和videoRendererNode:
- (void)createTvNode {
self.tvNode = [[SCNScene sceneNamed:@"Art.scnassets/tv_scene.scn"].rootNode childNodeWithName:kTVNode
recursively:NO];
self.tvNode.geometry.firstMaterial.diffuse.contents = [[UIColor blackColor] colorWithAlphaComponent:1.0f];
self.tvNode.movabilityHint = SCNMovabilityHintFixed;
self.tvNode.name = kTVNode;
[self addChildNode:self.tvNode];
}
- (void)createVideoRendererNode {
self.videoRendererNode = [SCNNode new];
SCNVector3 vector = [Utils getBoundingBox:self.tvNode];
self.videoRendererNode.geometry = [SCNBox boxWithWidth:vector.x - 0.04f
height:vector.z - 0.06f
length:0.005f
chamferRadius:0.0f];
self.videoRendererNode.position = SCNVector3Make(0.0f, -0.008f, 0.01f);
self.videoRendererNode.eulerAngles = SCNVector3Make(M_PI_2, 0.0f, 0.0f);
self.videoRendererNode.name = kVideoRendererNode;
self.videoRendererNode.geometry.firstMaterial = [self mainMaterial];
[self.tvNode addChildNode:self.videoRendererNode];
_currentTimeNode = [CurrentTimeNode node];
_currentTimeNode.position = SCNVector3Make(-0.025f, -0.1f, 0.003f);
[self.videoRendererNode addChildNode:_currentTimeNode];
}
這里代碼比較簡(jiǎn)單域那,設(shè)置大小,位置猜煮,和默認(rèn)材質(zhì)次员。
重點(diǎn)來了:
- (void)updateVideoNodeWithPlayer:(AVPlayer *)player {
// 1
SCNMaterial *mainMaterial = [self mainMaterial];
// 2
[_player pause];
[_player replaceCurrentItemWithPlayerItem:nil];
// 3
if (player == nil) {
self.videoRendererNode.geometry.firstMaterial = [self mainMaterial];
_player = nil;
}
// 4
else {
SCNMaterial *playerMaterial = [SCNMaterial new];
_player = player;
playerMaterial.diffuse.contents = player;
self.videoRendererNode.geometry.materials = @[playerMaterial, mainMaterial, mainMaterial, mainMaterial, mainMaterial, mainMaterial];
[_player play];
}
}
下面一步一步解釋:
- 獲得默認(rèn)材質(zhì)。
- 恢復(fù)當(dāng)前對(duì)象的_player對(duì)象
- 如果參數(shù)player對(duì)象為nil對(duì)象王带,那么我們將videoRendererNode的材質(zhì)設(shè)置為默認(rèn)材質(zhì)淑蔚,同時(shí)將_player對(duì)象設(shè)置為nil對(duì)象。
- 參數(shù)player對(duì)象不為nil對(duì)象愕撰,我們先初始化一個(gè)SCNMaterial對(duì)象(playerMaterial)刹衫,同時(shí)將player對(duì)象保存醋寝。因?yàn)镾CNMaterial的diffuse.contents接受一個(gè)id類型,也就是說任何類型的對(duì)象都可以作為材質(zhì)的內(nèi)容带迟。這里我們將AVPlayer對(duì)象作為SCNMaterial的材質(zhì)內(nèi)容音羞。設(shè)置好材質(zhì)內(nèi)容后,設(shè)置視頻節(jié)點(diǎn)幾何體的材質(zhì)仓犬。上面都準(zhǔn)備工作做好后嗅绰,播放視頻。
總結(jié)
其實(shí)AR視頻播放并不是很難婶肩,重點(diǎn)就是怎么將視頻渲染到模型上面办陷。