zoukankan      html  css  js  c++  java
  • 【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
    ------playableDuration:%f
    ------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

  • 相关阅读:
    JVM系列四:生产环境参数实例及分析【生产环境实例增加中】
    JVM系列三:JVM参数设置、分析
    JVM系列二:GC策略&内存申请、对象衰老
    JVM系列一:JVM内存组成及分配
    windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码
    微信小程序使用字体图标
    Jetson tx2 串口通信
    categorical[np.arange(n), y] = 1 IndexError: index 2 is out of bounds for axis 1 with size 2
    cannot import name '_imaging' 报错
    VS2015 opencv 无法打开文件“opencv_calib3d330d.lib”
  • 原文地址:https://www.cnblogs.com/weicyNo-1/p/12564512.html
Copyright © 2011-2022 走看看