如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件

问题:今天接到一个项目,负责弄需求的美眉跟我讲能不能做一个原型能够加载Collada文件,流程如下:

  1. 用户用app下载Collada 压缩包(如内购项目)
  2. 压缩包解压
  3. 展示Collada文件里的内容

我开始google各种能够快速搞定需求的工具以及类库,看了下Unity3D,感觉这胖子挺臃肿的,对胖子没兴趣。苹果的SceneKit好像做3D还不错,性能高还是原生,原生态的东西味道应该不错,下面有食用方法。

步骤一:

打开不是给人看的Apple Doucmentation,经过两眼球左右互搏后有重大发现就是苹果没有教会我什么魔法能够直接搞定这个需求,我表示很沮丧。

最终决定使用简单粗暴的方法硬把.dae文件下载到沙盒然后在runtime中读取

结果Xcode爆出:

scenekit COLLADA files are not supported on this platform

我也想爆粗。。。。。

看来没办法了,只能老老实实的自己写。

步骤二:

新建项目选择Game template,SceneKit

首先,要搞个Collada文件(.dae),没弄Maya很久了,下载了个免费的blender,把弄好的的dae文件丢到art.scnassets里边去。

步骤三:

先搞两盘盘炉石或者去斗鱼看看露半球

然后呢。。。

没然后了。

步骤四:

有的时候思路会自己送上门的,想读取文件在runtime又不让我操作compile-time,那种只能看不能摸的感觉你懂的。

既然苹果能够在scnasets目录下读取.dae那肯定用了些魔法,看看build logs到底做了些什么。

显然发现了什么,嗯似乎调用了copySceneKitAsets,正是这玩意最终调用了scntool去优化.dae文件

步骤五:

要挖坑了,要搞清楚为什么请找到这个目录去挖

(/Applications/Xcode/Contents/Developer/usr/bin)

找找发现这两个宝物 copySceneKitAsets、 scntool。

步骤六:

用户付费后下一步应该调用Api加载.dae

先建一个名叫product.scnassets的文件夹

运行下边脚本

./copySceneKitAssets product-1.scnassets/ -o product-1-optimized.scnassets

压缩打包生成的文件然后丢到服务器去

步骤六:

接下来是重体力活

我是用AFNetworkingSSZipArchive

在GameViewController.m 中施工

流程大概是这样,在viewDidLoad:中加入下载zip压缩包,解压的代码

- (void)viewDidLoad {
    [super viewDidLoad];
    [self downloadZip];
}

- (void)downloadZip {

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

    NSURL *URL = [NSURL URLWithString:@"http://www.XXXXXXX.com/product-1-optimized.scnassets.zip"];

    NSURLRequest *request = [NSURLRequest requestWithURL:URL];

    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {

        NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];

        return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];

    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {

        NSLog(@"File downloaded to: %@", filePath);

        // Unzip the archive

        NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

        NSString *documentsDirectory = [paths objectAtIndex:0];

        NSString *inputPath = [documentsDirectory stringByAppendingPathComponent:@"/product-1-optimized.scnassets.zip"];

        NSError *zipError = nil;

        [SSZipArchive unzipFileAtPath:inputPath toDestination:documentsDirectory overwrite:YES password:nil error:&zipError];

        if( zipError ){

            NSLog(@"[GameVC] Something went wrong while unzipping: %@", zipError.debugDescription);

        }else {

            NSLog(@"[GameVC] Archive unzipped successfully");

            [self startScene];
        }

    }];

    [downloadTask resume];
}

东西下载完了然后就是加载了

// Load the downloaded scene

NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];

   documentsDirectoryURL = [documentsDirectoryURL URLByAppendingPathComponent:@"product-1-optimized.scnassets/cube.dae"];

SCNSceneSource *sceneSource = [SCNSceneSource sceneSourceWithURL:documentsDirectoryURL options:nil];

// Get reference to the cube node

SCNNode *theCube = [sceneSource entryWithIdentifier:@"Cube" withClass:[SCNNode class]];

简单说一下就是是用SCNSceneSource、SCNNode加载,好像等于没说看代码就好。

接下来就是流氓导演最熟悉的步骤,布景、灯光、摄像机。

// Create a new scene

SCNScene *scene = [SCNScene scene];  

// create and add a camera to the scene

SCNNode *cameraNode = [SCNNode node];

cameraNode.camera = [SCNCamera camera];

[scene.rootNode addChildNode:cameraNode];

// place the camera

cameraNode.position = SCNVector3Make(0, 0, 15);

// create and add a light to the scene

SCNNode *lightNode = [SCNNode node];

lightNode.light = [SCNLight light];

lightNode.light.type = SCNLightTypeOmni;

lightNode.position = SCNVector3Make(0, 10, 10);

[scene.rootNode addChildNode:lightNode];

// create and add an ambient light to the scene

SCNNode *ambientLightNode = [SCNNode node];

ambientLightNode.light = [SCNLight light];

ambientLightNode.light.type = SCNLightTypeAmbient;

ambientLightNode.light.color = [UIColor darkGrayColor];

[scene.rootNode addChildNode:ambientLightNode];

这是我最喜欢的部分模特上场

// retrieve the SCNView

SCNView *scnView = (SCNView *)self.view;

// set the scene to the view

scnView.scene = scene;

// allows the user to manipulate the camera

scnView.allowsCameraControl = YES;

// show statistics such as fps and timing information

scnView.showsStatistics = YES;

// configure the view

scnView.backgroundColor = [UIColor blackColor];

习惯性总结:

  1. 从服务器拿到Collada zip的压缩包
  2. 解压
  3. 读到内存里
  4. 展示
  5. 这个总结好像可有可无
时间: 2024-10-12 13:17:29

如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件的相关文章

Java中动态加载jar文件和class文件

概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下的jar文件以及classes目录下的class文件,另外像spring这类框架,也可以根据指定的路径扫描并加载指定的类文件,这个技术可以实现一个容器,容纳各类不同的子应用. Java类由于需要加载和编译字节码,动态加载class文件较为麻烦,不像C加载动态链接库只要一个文件名就可以搞定,但JDK仍提供了一整套方法来动态加载jar文件和class文件. 动态加载jar文件 // 系统类库路径 File libPath =

急!!!关于drools动态加载规则文件

最近遇到一个问题 需要使用drools动态加载规则文件 在网上找了点资料 看了几篇代码 基本都是与框架分离开的 现在需要将drools动态加载与spring框架集成  要是有这方面的大神希望可以指点一番  急~~~  需求:将规则文件存入数据库中 实现动态加载调用 与spring框架集成 还要考虑到线程安全 要是有经验的大神 一定指点一番 谢谢啦

两种动态加载JavaScript文件的方法

两种动态加载JavaScript文件的方法 第一种便是利用ajax方式,第二种是,动静创建一个script标签,配置其src属性,经过把script标签拔出到页面head来加载js,感乐趣的网友可以看下 动态加载script到页面大约有俩方法 第一种便是利用ajax方式,把script文件代码从背景加载到前台,而后对加载到的内容经过eval()实施代码.第二种是,动静创建一个script标签,配置其src属性,经过把script标签插入到页面head来加载js,相当于正在head中写了一个<sc

为了提高性能,如何动态加载JS文件

超级表格是一款多人协作的在线表格,程序相当复杂,用到十几个JS文件.但是有些文件是在打开某些类型的表格时才需要加载. 例如,只有当打开甘特图表格时,才需要加载gantetu.js文件. 那么问题来了,为了减少js文件数量和请求,如何在需要时自动加载js文件呢? 办法如下. //动态加载js文件function mcss_importJS(js){ var oHead = document.getElementsByTagName('HEAD').item(0); var oScript= doc

Java_Java中动态加载jar文件和class文件

转自:http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下的jar文件以及classes目录下的class文件,另外像spring这类框架,也可以根据指定的路径扫描并加载指定的类文件,这个技术可以实现一个容器,容纳各类不同的子应用. Java类由于需要加载和编译字节码,动态加载class文件较为麻烦,不像C加载动态链接库只要一个文件名就可以搞定,但JDK仍

动态加载script文件

动态加载script文件:   http://www.cnblogs.com/skykang/archive/2011/07/21/2112685.html

jquery如何动态加载js文件

jquery如何动态加载js文件:本章节和大家分享一下几种动态加载js文件的方法,希望能够给需要的朋友带来帮助.方法一: $.getscript("test.js"); 方法二: function loadjs(file) { var head = $('head').remove('#loadscript'); $("<scri"+"pt>"+"</scr"+"ipt>").att

Qt动态加载ui文件(实现加载客户自定义的一些widget,如QVTKWidget)

利用Qt动态加载ui文件主要是实现ui设计和软件设计的分离,ui只需要向编程人员提供各个控件名称即可.这样做可以满足软件设计后期,由于客户需求,ui风格多变的情况下,不影响编程人员的开发. 具体实现:网上资料较多,一般利用QuiLoader ,只能加载Qwidget 或者QFrame,以下代码主要实现加载的Qwidget 窗口的子窗口有一些用户自定义的Widget ,这里我想加载的是QVTKWidget QString uiFilePath = "E:\\TASK\\CTSoftware\\Qt

[转载] Java中动态加载jar文件和class文件

转载自http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下的jar文件以及classes目录下的class文件,另外像spring这类框架,也可以根据指定的路径扫描并加载指定的类文件,这个技术可以实现一个容器,容纳各类不同的子应用. Java类由于需要加载和编译字节码,动态加载class文件较为麻烦,不像C加载动态链接库只要一个文件名就可以搞定,但JDK仍