【iOS】VR實踐--GVR的簡單使用


  VR是個比較火的話題,在iOS中集成全景和VR播放功能,是非常值得考慮和去實踐的。最近公司也准備在APP中集成VR功能。所以我也就了解了下VR功能的開發。目前有一些能幫助我們快速實現VR的項目,其中Google提供的GVRSDK(Google VR SDK)就是非常好的代表,基於此,我們可以快速地實現一個性能不錯的全景和VR播放器。(圖片全景播放+視頻全景播放)

  廢話不多說,直接擼代碼

一、SDK的導入

  GVRSDK的導入也是很簡單的,我們可以通過cocoapods導入。

target 'VRDemo' do
  # Comment the next line if you don't want to use dynamic frameworks

  # Pods for VRDemo
  pod 'GVRSDK'

  target 'VRDemoTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'VRDemoUITests' do
    # Pods for testing
  end

end

 

導入成功后就是這樣的結果了。

二、全景圖的加載展示

GVRSDK提供全景圖片播放的類是GVRPanoramaView,它支持兩個load接口。

/**
 * Load a 360-Panorama image from @c UIImage of type ::kGVRPanoramaImageTypeMono.
 *
 * If image is nil, it clears the view.
 */
- (void)loadImage:(UIImage *)image;

/**
 * Load a 360-Panorama image from @c UIImage of type ::GVRPanoramaImageType.
 *
 * If image is nil, it clears the view.
 */
- (void)loadImage:(UIImage *)image ofType:(GVRPanoramaImageType)imageType;

從接口中可以看出,它並不是直接加載網絡圖片,而是使用的UIImage。所以在使用這兩個接口之前,需要先從網絡上下載圖片資源。

枚舉類型GVRPanoramaImageType的有兩個可選值(kGVRPanoramaImageTypeMono和kGVRPanoramaImageTypeStereoOverUnder)。前者指定單個圖像源圖像,后者指有上下兩部分圖像源的圖像,上半部分對應左眼,下半部對應右眼。

GVRPanoramaView的父類GVRWidgetView,從GVRWidgetView頭文件中看出,它可以允許操作某些屬性,如在View上是否顯示信息按鈕、跳轉VR的按鈕等,如展示模式(嵌入父View/全景/全景+VR/)。我們根據需要在GVRPanoramaView的子類中設置好值。GVRWidgetView還提供代理,可以幫我開發者去了解GVRPanoramaView的load情況(如load成功或失敗)。

看了上面的分析,我們就知道怎么做了,我們可以使用常用的SDWebImage來下載圖片然后加載全景圖。

[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:VR_IMG_URL] options:SDWebImageScaleDownLargeImages progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
        float progress = receivedSize*100/expectedSize;
        NSLog(@"當前下載進度:%.2lf%%",progress);
        
    } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
        if (image) {
//            @autoreleasepool {
                [self.panoramaView loadImage:image];
//            };
        }
        if (error) {
            NSLog(@"下載圖片失敗");
        }
    }];
    
//  自定義一些相關配置
- (GVRPanoramaView *)panoramaView { if (!_panoramaView) { _panoramaView = [[GVRPanoramaView alloc]initWithFrame:self.view.bounds]; _panoramaView.enableTouchTracking = YES; _panoramaView.enableInfoButton = YES; _panoramaView.enableFullscreenButton = YES; _panoramaView.enableCardboardButton = YES; } return _panoramaView; }

當然一些加載進度和placeholder的展示需要我們自己添加。我這里沒有自己添加,之后可以根據不同要求進行自定義設置。

三、全景視頻的加載展示

GVRSDK提供全景圖片播放的類是GVRVideoView,它支持load和對視頻源播放、暫停和停止的控制

/**
 * Load a local or remote video from a url and start playing.
 *
 * The video is assumed to be of type ::kGVRVideoTypeMono.
 */
- (void)loadFromUrl:(NSURL*)videoUrl;

/**
 * Load a local or remote video from a url and start playing.
 *
 * The video type is set by @c videoType.
 */
- (void)loadFromUrl:(NSURL*)videoUrl ofType:(GVRVideoType)videoType;

/** Pause the video. */
- (void)pause;

/** Start or resume the video. */
- (void)play;

/** Stop the video. */
- (void)stop;

loadFromUrl:中的參數videoUrl,不僅可以是線上的視頻源的URL,還可以是本地的視頻資源的URL,比GVRPanoramaView的load接口更強大。我們可以不用去操心下載視頻的問題。

枚舉類型GVRVideoType的有三個可選值。 kGVRVideoTypeMono、 kGVRVideoTypeStereoOverUnder 和 kGVRVideoTypeSphericalV2,kGVRVideoTypeMono代表單個視頻源的視頻,kGVRVideoTypeStereoOverUnder是有上下兩部分視頻源的視頻,kGVRVideoTypeSphericalV2代表是球形視頻源的視頻。

GVRVideoView的也是父類GVRWidgetView。

GVRVideoView還提供GVRVideoViewDelegate,代理中方法可以獲得視頻的播放進度。

#pragma mark - UINavigationControllerDelegate
// 將要顯示控制器
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    // 判斷要顯示的控制器是否是自己
    BOOL isShowHomePage = [viewController isKindOfClass:[self class]];
    [self.navigationController setNavigationBarHidden:isShowHomePage animated:YES];
}

#pragma mark - GVRVideoViewDelegate
- (void)widgetViewDidTap:(GVRWidgetView *)widgetView {
    if (_isPaused) {
        [_videoView play];
    } else {
        [_videoView pause];
    }
    _isPaused = !_isPaused;
}

- (void)widgetView:(GVRWidgetView *)widgetView didLoadContent:(id)content {
    NSLog(@"Finished loading video");
    [_videoView play];
    _isPaused = NO;
}

- (void)widgetView:(GVRWidgetView *)widgetView didFailToLoadContent:(id)content withErrorMessage:(NSString *)errorMessage {
    NSLog(@"Failed to load video: %@", errorMessage);
}

- (void)videoView:(GVRVideoView*)videoView didUpdatePosition:(NSTimeInterval)position {
    // Loop the video when it reaches the end.
    NSLog(@"-------didUpdatePosition:::::%f\n------playableDuration:%f\n------duration:%f",position,videoView
             .playableDuration,videoView.duration);
    if (position == videoView.playableDuration || isnan(position)) {
        [_videoView seekTo:0];
        [_videoView play];
    }else{

    }
}

- (GVRVideoView *)videoView {
    if (!_videoView) {
        _videoView = [[GVRVideoView alloc]initWithFrame:CGRectMake(0, 0, MAX(SCREEN_WIDTH, SCREEN_HEIGHT), MIN(SCREEN_WIDTH, SCREEN_HEIGHT))];
        _videoView.delegate = self;
        _videoView.enableFullscreenButton = YES;
        _videoView.enableCardboardButton = YES;
        _videoView.enableTouchTracking = YES;
        _videoView.enableInfoButton = NO;
    }
    return _videoView;
}

當然如果是x正式應用中,placeholderView、ProgressHUD、播放進度條和播放按鈕這些都是必不可少的。耳機的插入和拔出也是需要處理的,我這邊就沒有進行處理。

簡單demo。使用的話需要pod install


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM