前文:Away3D断断续续用了一段时间了,三维相关的很多算法,计算转换还是有点绕,整理些自己觉得还有点意思东西,希望大家有用。
三维开始,Away3D构架你场景那几行代码各处都有,这里就不copy了,总之在构建完成之后,我们看看怎样去加载一个精细模型并解析
正式开始:
一、首先对Away3D中loader包下面几个类做简单介绍(先了解了才能知道知道怎么去用)。
Away3D类库中负责加载解析的相关类主要在loader包下,当然还有个全局资源管理的AssetLibirary相关。具体职能如下:
- AssetLoaderContext 负责资源加载过程的的一些全局控制属性,主要集中在对于资源URL的重定向控制,已加载的二进制资源命名管理等。一般情况下不用
- AssetLoaderToken 内含一个AssetLoader引用,负责资源加过程中的事件控制
- ResourceDependency 记录资源URL(或ID)与解析文件的对应关系。
- SingleFileLoader 实质性的文件加载类,解析调度类。内含URLLoader引用负责加载数据,根据对数据类型的判断(或用户设置)来获取对应数据解析器parser对数据做最终的解析。
- AssetLoader 资源加载控制类,负责针对不同URL或者二进制数据进行解析,对模型所附带的资源列表(uv,纹理图片)进行逐个加载解析。内含对AssetLoaderContext中设置属性的使用,对parse()的调用,对resourceDependency的逐个调用或者直接接卸(retrieveAsRawData)
- Loader3D 继承自ObjectContainer3D,内含一个AssetLibraryBundle或AssetLoader实例(通过属性_useAssetLib属性来控制选择使用全局资源管理还是单独构建),可以直接将加载解析的内容转换成3D可显示的模型并封装在自身容器中。
- Parser ALL_BUNDLED 定义了当前支持的几种类型的数据解析器,使用AssetLoder. enableParsers 可以设置SingleFileLoader当前支持的解析类型
- ParserBase 解析器基类,各具体类型的解析器继承自此。负责解析过程的调用,异步逐帧加载,事件的分发等。。
- 各个XXXParser 具体的解析类 很直观,不同类型的模型文件对应不同的具体解析器
- AssetLibrary AssetLibraryBundle 这两个类提供静态方法实现模型加载和全局的模型资源管理。
上述众多代码中,红色标注的三个类基本完成了模型加载解析的主要功能。ResourceDependency,AssetLoadetToken,AssetLoaderContext在过程中负责一些简单调调度和数据封装。 Loader3D实在AssetLaoder外层做了一次包装。 AssetLibraryBundle则是通过维护对应明明空间的AssetLoader来提供对资源的统一管理(目前我查看的源码版本这块还尚未完成)
二、使用方式和各区别
使用方式分为三种
1、直接使用AssetLoader
var assetLoader:AssetLoader = new AssetLoader;
//设置解析器类型(根据模型文件格式)
AssetLoader.enableParser( OBJParser ); //通过事件监听获取解析的结果资源。一般只关心AssetType为mesh的
//(注LoaderEvent.RESOURCE_COMPLETE事件表示当前模型全部解析完成)
assetLoader.addEventListener(AssetEvent.ASSET_COMPLETE,onAssetComplete); //调用Load或者LoadData接口开始加载解析
assetLoader.load (new URLRquest("./demo.obj"));
2、使用AssetLibrary
AssetLibrary.enableParser( OBJParser );
AssetLibrary.addEventListener(AssetEvent.ASSET_COMPLETE,onAssetComplete);
AssetLibrary.loadData(new HeadModel());
看着和1类似吧。其实内部也差不多。通过静态的接口调用,在AssetLibraryBundle的单例实例中通过命名空间获取AssetLoder来解析。优点一、资源维护,2、资源共享(同一命名空间下的同名资源<比如两个文件使用的同一个图片资源等>可以共享)。这边资源通过ID缓存的代码已经实现,但是读取(也就是共享)的部分...期待后续版本完善吧
3、使用Loader3D
这个就更简单了,和1一样,不过关于结果,可以直接把Loader3D添加到场景去显示。因为获取的模型会自动添加到当前Loder3D中 ,别忘了他也是个ObjectContainer3D对象啊
三、模型解析环节问题补充
现状:模型解析,这里面支持的格式有AWD,OBJ,3DS,DAE,DXF,MD2,MD5等。。总体来说种类是够用了。
ImageParser支持长用的png,jpg,gif等(其实是flash支持的他都支持,flash不支持,还是自己使用外部工具转吧)
问题: ------不支持多材质的模型解析(一个模型使用多张贴图)。
来吧,直接改源码吧,谁让这块卡主了就没法用了,总不能挨个去给模型做UVW展开的拼接操作(俺是码农,不是设计师啊)
目前解决了OBJ和3DS的多材质问题。思路拿出来跟大家分享下:
仔细查看OBJParser和MaxsDSParser的源码,发现这边代码不是没有获取多个图片的纹理信息,而是没有把纹理贴图使用到对应的集合面上去。小弟于是这样想的,最终无非是几何面找到对应纹理或者对应的纹理找到几何面。考虑纹理一般是由url或者ID的,而几何面是不断组装起来的。 我们还是让几何面来找纹理吧,毕竟纹理有现成的标记不是
解析过程中,每个面都有使用的纹理,这个在模型文件中是有定义的,关于OBJ和3DS中的模型记录方式可参考下面的两个地址。当我们吧面信息解析成三维SubGeometry的时候,我们需要记录下来它使用是哪个纹理,这样方便纹理加载后我们去寻找。 直接给SUBGeometry添加了个纹理ID属性 materialID,同时也映射到了SUBMesh上(纹理最终是给subMesh贴的),后面的在最后applayMaterial的时候... (后面你懂得,遍历查找就是了)O(∩_∩)O~
考虑没个面都贴一个张图片,模型面特别多的时候subGeomtry会比较多,而这会影响最终性能。最后提供一个优化方案,把所有使用同一纹理的subGeomtry在接卸过程中合并成一个,然后再贴纹理...
四、这个loader包的设计问题???
表示标题这样写是噱头,希望下面几点大家可以关注下。
1、上面的AssetLibrary没实现完成的问题
2、AssetLoaderContext,这个类一直没说怎么用。 简单补充下、
1)、url映射。如果模型文件建模的时候使用的不是相对模型的路径,那么我们加载的时候则是需要将这个地址做重新映射的,要不然肯定家在不到图片。。 使用属性dependencyBaseUrl可以修改整体路径。使用Mapurl可以修改url的映射关系单个调整。
2)、资源的缓存,context里有个mapUrlToData 和getDataForUrl 接口,很明显的存取。结果这个在代码中没有存的(...),取的时机也不对(这块应该算是未完成功能吧,继续同1,期待下个版本)
3、模型解析ParserBase中有个通过setTimeout来逐帧解析文件,完成一定后开始退回主线程处理渲染...这个小设计还是很巧妙的。 单线程中模拟多线程的数据处理,不卡频,后面应该用得到这种思路(大家有更好的方案也可以告知一下,非常感谢!)
解析这块大致这样了,总体来说不够完整,有待提高。关于中间多个类的调用相互关系的各种复杂,觉得应该更简化点,自己没什么好点子,大家有的话可以告诉我。先谢过