如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件
问题:今天接到一个项目,负责弄需求的美眉跟我讲能不能做一个原型能够加载Collada文件,流程如下:
- 用户用app下载Collada 压缩包(如内购项目)
- 压缩包解压
- 展示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
压缩打包生成的文件然后丢到服务器去
步骤六:
接下来是重体力活
在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];
习惯性总结:
- 从服务器拿到Collada zip的压缩包
- 解压
- 读到内存里
- 展示
- 这个总结好像可有可无
如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件的更多相关文章
- Java_Java中动态加载jar文件和class文件
转自:http://blog.csdn.net/mousebaby808/article/details/31788325 概述 诸如tomcat这样的服务器,在启动的时候会加载应用程序中lib目录下 ...
- Android应用安全之外部动态加载DEX文件风险
1. 外部动态加载DEX文件风险描述 Android 系统提供了一种类加载器DexClassLoader,其可以在运行时动态加载并解释执行包含在JAR或APK文件内的DEX文件.外部动态加载DEX文件 ...
- js动态加载css文件和js文件的方法
今天研究了下js动态加载js文件和css文件的方法. 网上发现一个动态加载的方法.摘抄下来,方便自己以后使用 [code lang="html"] <html xmlns=& ...
- 两种动态加载JavaScript文件的方法
两种动态加载JavaScript文件的方法 第一种便是利用ajax方式,第二种是,动静创建一个script标签,配置其src属性,经过把script标签拔出到页面head来加载js,感乐趣的网友可以看 ...
- QUiLoader 动态加载.ui文件
动态加载UI文件是指,用 Qt Designer 通过拖拽的方式生产.ui 文件.不用 uic工具把.ui 文件变成等价的 c++代码,而是在程序运行过程中需要用到UI文件时,用 QUiLoader ...
- 动态加载JS文件,并根据JS文件的加载状态来执行自己的回调函数
动态加载JS文件,并根据JS文件的加载状态来执行自己的回调函数, 在很多场景下,我们需要在动态加载JS文件的时候,根据加载的状态来进行后续的操作,需要在JS加载成功后,执行另一方法,这个方法是依托在加 ...
- 详解QUiLoader 动态加载.ui文件
http://blog.chinaunix.net/uid-13838881-id-3652523.html 1.适用情况: 动态加载UI文件是指,用 Qt Designer 通过拖拽的方式生产.ui ...
- ExtJS4.x动态加载js文件
动态加载js文件是ext4.x的一个新特性,可以有效的减少浏览器的压力,提高渲染速度.如动态加载自定义组件 1.在js/extjs/ux目录下,建立自定义组件的js文件. 2.编写MyWindow.j ...
- Ext JS学习第十天 Ext基础之动态加载JS文件(补充)
此文用来记录学习笔记: •Ext4.x版本提供的一大亮点就是Ext.Loader这个类的动态加载机制!只要遵循路径规范,即可动态加载js文件,方便把自己扩展组件动态加载进来,并且减轻浏览器的压力. • ...
随机推荐
- HTTPS 和 HTTP
https://www.zhihu.com/question/52790301
- MapReduce 过程分析
原文地址:http://blog.jobbole.com/81676/ 2.WordCount处理过程 上面给出了WordCount的设计思路和源码,但是没有深入细节,下面对WordCount进行更加 ...
- Qt窗口的屏幕居中显示
QDesktopWidget *pDesk = QApplication::desktop(); login->move((pDesk->width() - login->width ...
- 粒子拼字效果(getImageData方法)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Percona 5.7安装
一.从官网下载Percona5.7 地址:https://www.percona.com/downloads/Percona-Server-5.7/LATEST/ 需要注意是服务器的版本.我这里选择的 ...
- SQL Server 2008R2数据库文件导入到SQL Server 2008数据库中
最近,电脑重装系统之后,安装了SQL Server 2008.附加数据库文件的时候,发现无法附加,提示版本不对.想起来,原来的数据库版本是SQL Server 2008R2.低版本的数据库管理工具无法 ...
- 【微信开发】常用 api
[微信开发]api 一. 开发文档 二. 调试工具 三. api 1. 获取 token - https://api.weixin.qq.com/cgi-bin/token?grant_type=cl ...
- 修改Shp文件名称
IWorkspaceFactory factory = new ShapefileWorkspaceFactoryClass(); IWorkspace pworkspace = factory.Op ...
- MongoDB Replica Set 选举过程
什么是选举? 选举是副本集选择某个成员成为primary的过程.primary是一个副本集中唯一能够接收写操作的成员. 下面的事件能够引发一次选举: 第一次初始化一个副本集 Primary失效.rep ...
- app进入后台之后接收到通知,点进去进入新的页面,再次进入后台,再点击通知进入页面(,两次通过通知进入的页面,创建了两次,会多一个页面,)解决办法监听
在点击通知进入的页面的 //UIApplicationWillResignActiveNotification是app即将进入后台的方法 //增加监听使它在进入后台之前pop上一个页面 - (void ...