守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 2105|回复: 0

[基础入门] flascc移植问题流水账

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52620
    钢镚
    1422

    开源英雄守望者

    发表于 2015-3-11 11:00:32 | 显示全部楼层 |阅读模式

     把demo顺利移植到几个pc和移动平台后,便不觉雄心博博,想要一股作气,把flash“平台”也拿下。但flash终规不是一个“正常的”posix类平台,adobe相对其它几家操作系统级厂商来说,在打造平台环境及工具链方面的功力确实还是差了点,导致困难重重,其编译调试过程更是让人叫苦连天,至今仍在苦苦挣扎中。现打算每天一记,把所有的陷井和进步都总结在案,看看需要多少天才能克尽全功!

     12.6 今天算是有了较大进展,可以加载一个外部图片,并画出来了!

      由于是第一次写,先补记一下这之前的所有经历。大概在三周前,由同事Z开始着手第三方库的移植,如iconv/freeimage/freetype/lua等等。由于之前在做其它平台时已经折腾过好几遍,知道这类开源库的交叉编译都有大同小异的流程,因此虽然繁琐,但也还正常,没有碰到太多诡异问题。令我留下印象的有两件事,一是有些库在生成.a文件时用的是AR,有的是用RANLIB,在配置交叉编译环境时应该两个都写上,否则刚好漏掉它需要的那个时,生成的.a文件其实是用本机(native)格式的,最终链接时肯定不过,会提示can't find symbol table之类的信息。二是在最后生成可执行文件时,出了一个unresolved extern:avm2_tramp_alloc。当时找遍所有标准库,都没发现哪个里面有这符号,在google上也搜不到任何信息,正当焦头烂额时,偶然发现sdk/share下面有个avm2_tramp.cpp文件,原来需要的函数定义就在这里面了,把它加到编译列表里,链接就成功了。但是也没有深究这个文件到底是做什么用,以及为什么会采用这种提供方式。(要做的事太多了,还来不及打这种支线剧情)。

      其实链接成功的只是一个简单的空壳程序,还完全不包含demo的任何内容,但是这里面对主循环和消息分发以及系统窗口等概念做了提炼,并统一到引擎的系统接口层中。这个接口层是一个用来屏蔽不同系统对应用程序生命周期管理的中间模块,旨在为其上的逻辑层提供统一的入口点、事件机制。一般的系统都是由main函数开始,需要自己建立事件循环并轮询之,但是有的系统自建了事件循环和分发机制,如果不屏蔽这个差别,那么在写上层应用时,就不可避免的还要涉及平台条件编译问题,很不美观。而屏蔽的结果就是,写应用时不再从main/winmain开始了,变成了像MFC一样继承一个app类并定义一个该类的全局对象来启动。多年前也不明白MFC种种被人诟病的手法是出于何故,只有当自己真正做到时,才理解前人的一片苦心。

      在这个空壳能在flashplayer里运行起来后,就开始想办法往里面一点点加东西,当然最重要的是都显示出来,让每次加的东西都能看到有什么不同。因为其它平台的基础功能都早已经做好,demo已经做到了稍显复杂的程度,想直接拿来测试肯定是不行的。于是为它专门写了另一个小程序,先不跑脚本和对象系统,而是直接在初始化时创建一次资源,在帧函数里绘制它们。

      首先当然是用stage3d的api来做,先确认功能本身是正常的。参照sdk中的例子,刷出颜色,画了三角形后,大家都舒了一口气,因为在把自己的程序编成flash后能看到东西(其实还没涉及到半点自己的逻辑),剩下的就是慢慢调了,于是觉得用C写flash这回事也该算是靠谱了。可后面的事情证明这口气还真是舒得早了点……

      确认stage3d功能正常后,就开始想法将其封装到统一的抽象接口之后。因为需要跨渲染api,所以对逻辑层定了一套渲染抽象接口,并已经有了dx9/opengl/opengles三套实现,现在需要新增一套用于flash的实现。封装的过程中碰到几个问题:

      1)一开始没搞懂VertexBuffer相关的几个接口里参数的含义,误以为flash只支持多流顶点,然而我在逻辑层都是以单流方式使用的,于是只好在实现as3mesh.unlock_vertex时,再手动拆分一次顶点到多个数组。虽然已经做好了但后来才发现setVertexBufferAt这个api的第3参数offset,其实是指不同属性在同一数组中的偏移(这正是单流的关键),而之前一直误以为是起始顶点偏移,于是很快把它改回来了。

      2)IndexBuffer.updateFromByteArray这个api,一定是有bug。不论IB里填什么,最终都只能画出第1个三角形。当时我百思不得骑姐,反复的修改代码调整数据做各种测试,要知道即使是那么简单的一个空壳最后链接一次都要几分钟,那样子的debug真是叫人吐血啊!最后我实在找不出问题了,但突然想到一个简单的验证方法,即去看flascc自带的sample是否正常,第12个12_stage3d里有两个例子,第一个是本身就只画一个三角形,太偷懒了;第二个是SpaceTriangle,名字看起来又是三角形,但看里面的代码,“ship”发射的"missle"应该是个四边形(4顶点6索引),可是把它编出来运行后竟然也是——只有三角形!这下我明了了,却也绝望了,连它自己的例子都不行,那就是说它一次真的只能画一个三角形了,那还怎么渲染复杂模型啊!当时真有种眼前一黑的感觉,所有努力都白费了,毫无意义啊,更让我沮丧的是觉得愧对同事K,之前我一直向其宣称引擎的跨平台特性并声称跨到flash上也只是时间问题,导致他对此充满了希望并将其项目中的核心程序派过来共同研究以求尽早得出成果应用于他的项目。我能做的只有在flascc的论坛上发了帖子报告此bug,然后回家睡觉等回应。虽然大概也相信这肯定只是个bug不可能是其真实特性,但按adobe向来的态度还真不知道它们几时能改好,而我们就只能一直被吊着了。

      待补……

       12.8 又是两天过去,对加载图片有了更多理解,并且也对移植工作流程做了改进,即在C里实现功能之前,先用纯as3实现一遍,在flashdevelop里编码、查找文档、调试都非常方便,先用as3写一遍,可以把大致流程梳理清楚,也可以确认想法是否正确,然后再在C里去写,可以减少很多无谓的排错时间。关于图片加载,用as3来做是非常方便的:Loader->URLRequest->BitmapData->Bitmap/Texture;除此外还可以通过Loader.loadBytes直接加载一段现成的字节流。比较奇特的是即使是后者也是异步的,不能马上得到结果,还是需要在回调中才能使用数据。把这个流程搬到C里,第一种方式正常,第二种却出错,总是提示IOError:不认识的文件类型,我在as3和C里都打出了ByteArray的头几个字节和长度,都是一样的,可as3行而C就是不行。这又间接证实了我那个猜测:flascc的ByteArray处理有bug,已经在它论坛上发过2个帖子,可是adobe的工作人员视而不见,几天前发布了一个依旧的是问题多多的所谓“1.0正式版”后,就放大假似的销声匿迹了,实在对他们的工作态度深为不满。

        接着试验了用引擎现有的freeimage模块加载图片,再把数据传BitmapData的做法,确认是可行的。但是速度慢得惊人,加载一张256x256的jpg,用时800ms,PNG/TGA分别为500/100ms,而这在“正常平台”下的C程序里用不了1ms。之后用as3加载此jpg做对比,发现只不过30ms,而这还是受限于异步加载所致的最小延迟底限,真实时间可能也不过1ms。之所以相差如此之大,原因也很简单:as3的类库自身当然都是用C写的,是用真正的C编译器生成了真正的机器码,而我们的C程序被flascc的“伪C编译器”编译后生成的是avm字节码,当然不在一个档次上。这也说明了一个道理:入乡随俗,既入了flash的戏,就要按它的规矩演。之前一直有种极端的心理,想做一套全功能的包打天下的引擎,然后原封不动移植到各平台,因此初接触flash时,面对它自身庞大的与我们本身功能重复的类库时,总是举棋不定,不知道到底是用它原生的好,还是用我们自己统一的好。现在总算有点醒悟了,之所以想用统一的,无非是因为代码直接复用(共用),流程不用修改,更重要是有一种“跨平台的虚荣感”;可是缺点很明显,速度慢,而且功能重复的C代码也加大了swf的体积,不管怎样,效率总是第一的,当一种结构导致低效时,无论怎样优秀的设计都不能弥补这种过失。所以,结果就是,为flash平台的资源加载重做一套流程,对应的也就是能“共用”的逻辑层次又往上提了一段,而被取代的那部份则变成了为适应不同平台而做的不同的接口层。

      12.11 今天adobe人终于活过来了,回了我的贴子解释了IndexBuffer.updateFromByteArray为什么不行的问题,原来是他们sdk里的sample写错了:传给IB的数据应该是uint16的但是他们写成了int!结果我是照搬例子代码的自然也就不行!擦,当初我就感觉不对,索引一般都是用16位的,可是看它写成int,而纯as3里确实也是写成vector.<int>,也就没有想过这里会有错,兀自纠结了半天,却原来是他们的笔误,真是吐血啊!今天刚好有两个同事都问我怎么把flash的ByteArray与C里的指针互转,这确实是个很关键的问题,两者的数据交互大多靠此,其实在flascc自动生成的as3++ api里,凡是带ByteArray参数的函数,都会多出一个void*参数来,这个参数就是我们要与之交互的C内存指针,而那个ByteArray参数,则应使用一个特殊的对象:internal::get_ram(),这个对象就是一个表示C里可用内存(俗称DomainMemory)的特殊ByteArray。

      12.14 周末了。这周本来计划要把一个显示2d地图块的demo做出来,前面进展都还顺利,但到最后因为脚本模块出现诡异bug而告罢。

        首先,搞明白了字体渲染的方法。之前认为要把freetype移植过来,用与其它平台一样的办法来产生texture。但经过freeimage的转变,预先就感到这种办法可能太慢,应该寻找flash自身的实现,结果在网上搜了下也看了下其它纯as3渲染引擎的做法,简单得令人吃惊:直接把一个textfield画到bitmapdata上!这不就是我们原来在2d引擎年代常用的技术吗?每一种对象都能将自己“光栅化”,转变成一符位图,其最终显示在窗口上,也不过是把这个位图贴到了窗口。可是自从进入GPU时代以来,这种做法逐渐变得陌生,不再普遍到每一个小对象都能单独“成像”,而是一般只对整个场景、整副界面,在调用某些特殊效果时,才事先渲染到RT。究其原因,还是批次的限制,使小对象的即需即渲变得不再高效。但是flash本身就是个软渲染引擎,让它做这种工作,可谓轻车熟路,于是利用textfield来生成字模位图,就又成了flash模式下的一道特殊风景。我先在纯as3里编码实现了以上思路,但往引擎中整合时,碰到几个问题:

        1)flash的texture.uploadFromBitmapData不支持设定子区域,必须是全图对全图,这对我引擎text对象的设计是个致使打击,我的做法是一行字生成一张texture,然后将每个字的bitmapdata逐一复制上去,可是在这flascc下没法实现了;

        2)字库的加载选择,也变得与往常迥异,需要大幅调整代码结构。

        对第1个问题,我数度犹豫,到底是把抽象隔离层做在font上还是text上。如果抽象在font上,只要font能提供每个字符的字模位图,那应用层无论按何种方式使用都变得平台无关了,但如抽象在text这种实际对象上,那么一旦有对字模位图的其它需求,就又得为其做两种实现。然而抽象font的难处就是上面提到的,但是如果换成抽象text则可绕过去。但最终我还是想了个bt的办法来顶住前者的困难,即一旦texture.upload被以子区域方式调用时,就为其临时创建一个等大的bitmapdata,之后的所有upload调用都把数据缓存在这个bitmapdata上,直到真正被settexture使用时,才即时上传到真正的texture上。对第2个问题,其实就是把原来的font和fontmgr两个类做成抽象接口,原来的实现改名为font_freetype,然后新增一个实现叫font_flash,程序在编译时即会确定所能获取到的fontmgr是freetype类型的还是flash类型的,其它模块如text等在使用时,只使用抽象接口就行了。记得最早的时候font体系是用win32的api做的,后来为了渲染质量换成了freetype,再后来为了跨平台直接去掉了win32 api,现在又增加了flash,真是分分合合,难以尽数。

        今天同事L告知碰到了一个诡异问题,在向lua注册引擎类时出现了难以解释的错误。这个模块按理来说是一个纯数据逻辑模块,在往其它平台移植时,它几乎半点没有改过就能正常运行,可是偏偏在flash下出错,真是既奇怪又不奇怪,对于flascc的各种问题,都习以为常了。相信他在反复的调试之后,应该能得出答案。



    本文来自:http://www.cnblogs.com/wellbye/a ... 8/fx_to_flascc.html


    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2024-3-29 10:11 , Processed in 0.098947 second(s), 34 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表