答辩结束

 毕业设计/论文工作终于“完成”了,不过接下来反倒比以前要忙许多。

 都说做科研要集团作战才有搞头,无奈现在这样单纯的人太少…奇怪的是目前各大公司都宣扬“牛人狩猎计划”,馋得大家围着一两个方向上演“百万大军过独桥”的好戏,力争自己能贴上牛屁股,结果到最后对自己的老本行一窍不通,连“牛”的任何部位都没能贴上。

 到处传言找工作不容易,却发现好马们一个比一个跳的勤。

Comments

DLC付费也疯狂

 从没想过《轩辕剑》系列会出付费DLC,轩迷们不免又要被痛宰一把了。作为投资方——大宇心中的小算盘昭然若揭:把一部游戏拆成两部分卖,更重要的是后者实际上起到剧情补完的作用:没玩过付费DLC也敢说自己玩过《云之遥》?

 当然从质量上看《兰茵篇》对于区区200多新台币来说可称得上是物有所值,但制作方给人感觉实在是太为了DLC而DLC,这次发售更是主打一些新增的周边产品。其次,类似于剧情补漏DLC这种模式国产rpg以后最好戒了算了,否则实在让人怀疑研发团队的诚意。

 联想到前段时间另外一部喜欢的作品《ZWEI ii plus》发售,很多人说国人缺乏创造力,模仿就成了混饭吃的唯一出路。但为了长远考虑,还请财主们允许team member尽量模仿到骨髓吧!

 总之,11小时的《兰茵篇》初体验给人感觉是欣慰的,但像本传那样目标全任务全装备的二周目只好等以后有空再说了。

Comments

更多关于flash的一些思考

 我对flash可以说是情有独钟的。

 记得在2001年,请同学在劳动南路代购了flash5英文版,在语言完全不通的情况下,逐渐摸清了时间轴和一些基本动画制作。但如果说首次了解flash这一名词,还得追溯到2000年《网友世界》(当时还是《网友》)创刊了。后来因为某期杂志上对美女闪客“哎呀呀”的专访,使得我从此踏上了拜师学艺之路。

 现在看来,我的flash学习之路并非一帆风顺,原因如下:

 首先,当时我并未意识到flash作为web媒体的作用,平时接触到的仅仅是一些大师们令人拍案叫绝的动画作品。直到2003年加入网民的行列之后才对此有所了解。

 其次,开始很长一段时间里,我仅能通过月刊或后来的半月刊来自学。由于学业的原因,根本无法借助书籍来海量学习,更别说求助“前辈”了。

 再次,我很快发现,纯粹的flash动画制作实际上需要很深厚的计算机美术功底,我在“专业不对口”的情况下硬坚持了几年。记得在2005年,还有幸帮助表哥的大学同学完成了课题设计(尽管现在看来那玩意似乎只是最终敷衍一下通识课老师而已)。

 2006年起,flash对我来说有了新的意义,即web媒体。起初热衷于flash整站建设,后来发现知识储备不足,又去学习php和js,可以说flash伴随着我遨游互联网长达7、8年之久。

 2008年,我开始着手重建hanyi.name,从此对flash也有了新的看法。

 近日,jobs在apple网站上发布了一篇《Thoughts on Flash》(原文链接:http://www.apple.com/hotnews/thoughts-on-flash/),更加加深了我对flash的某些担忧,这也是写作本文的初衷。

 我认为flash对用户最大的困扰在于其安全性和稳定性。我从去年开始尝试一些非IE引擎的浏览器,原因即在于网页中嵌入flash player时可能会发生负载过高的情况,最终发现问题还是出在flash player自身,后来索性在chrome上屏蔽了flash。

 同时对开发者而言,如果某个平台会对用户造成很多困扰,那么抛弃它也就在所难免了。这也是我最终不得不去深入学习js、jquery的原因。

 事实上,jobs提到flash只适用于pc。但我认为在未来移动计算和pc业务将重新融合(合久必分,分久必合?),留给flash的空间到底有多少就很难说了。

 Adobe是我非常尊敬的一家公司,但它也是一家非常热衷于发布新标准的公司(因为它有足够的话语权)。令人遗憾的是,Macromedia的出售或许只是为了创造“大奥多比时代”,在互联网开放平台风气日益浓厚的今天,商业巨舰缺少太多的灵活性,掌舵人的开明程度就将决定产品未来的生死。

 由此联想到近期热议的“云端之争”,rich client的未来依旧未卜。flash作为ms鄙视、google忽视、apple歧视的“悲剧儿”,到底是一条道走到黑,还是另辟蹊径,恐怕都将成为互联网时代的经典案例。

Comments

关于GrassrootDCM补完

 之前提到GDCM基层DCM类库是一个颇为强大的开源dicom文件基础类库。目前,GDCM已经专门针对vtk提供了应用程序接口,我们可以利用vtkGDCMImageReader和vtkGDCMImageWriter两个类完整支持DICOM标准V3的IO操作。

 但是获得GDCM后,遇到一些颇为棘手的问题。

 首先,GDCM对Win32平台只支持vc7.1以后的编译器,而现有的vtk则是采用vc6.0编译。即是说,如果编译GDCM时要cmake选择vtk的扩展项,就必须采用vc7.1以后的编译器重新编译vtk。

 其次,现有的工程均是采用vc6.0创建,如果将平台完全迁移至后续vc版本,就可能会影响目前的工程进度。

 另外,从vc6.0迁移至新版本中所带来的编码问题可能会影响到应用程序的稳定性。

 出于以上考虑,先尝试重新编译vtk,这里我们预设的编译平台为vs2005,即vc8.0。但注意不应覆盖原有vc6.0编译的vtk文件,即在cmake阶段改一下prefix属性值就可以了,其余操作不变。对于新install的vtk文件,我们将环境变量path中bin的原有vtkbin的设置改为新版本值(有些读者之前可能会选择将所有bin文件放入system32中,但是按修改path的方法较好,当然后者的修改方法是相对应的)。

 现在cmake从sourceforge上找来的GDCM2.0.x,仔细检查一些配置项,尤其是扩展vtk项一定要选,g后用vc8.0编译。这里不应出现任何error。现在看来,GDCM的安装步骤其实和vtk没有什么区别,但是对vtk和编译器的要求较严格。

 这里再总结一下我们针对vc6.0使用GDCM+VTK编程的基本思路:

 1、vc6.0引用库采用原有vc6.0编译生成的vtk文件。

 2、运行库采用vc8.0编译生成的vtk文件(即DLL文件)。

 3、在vc6.0中再引用vc8.0编译生成的GDCM文件。

 完成上述步骤,就可以使用vc6.0进行下一步工作了。要注意的是,vtk的运行库一定要更新为vc8.0新编译版本,否则我们一调用GDCM就会因为DLL版本不足而出错。

 关于gdcm的全套文档可以参考:

 http://gdcm.sourceforge.net

 这里要再次说明一下,gdcm完整支持dicomV3,这是vtkDICOMImageReader乃至ITK都无法与之相提并论的。在实际应用开发中,还要注意程序基础构架对选择开发平台的影响。

Comments

医学影像的基本文件存储格式与vtk集成方法

 毫无疑问,PACS已经是现代乃至未来医疗机构里不可或缺的基础设施之一,医学影像的基本存储格式就成为了标准化过程中的关键环节。

 ACR/NEMA联合发布了数字医学影像和通信标准,即DICOM。DICOM涉及的领域非常之多,NEMA上公布了DICOM的全部文档信息:

 http://medical.nema.org/

 此外,通常我们研究DICOM存储格式主要是为了实现文件压缩格式的转换,这里建议参考一些额外信息,以避免受到DICOM海量文档的困扰:

 http://www.dclunie.com/medical-image-faq/html/part8.html 

 这里我们主要讨论vtk对DICOM标准的支持情况。在早期vtk版本中并未直接提供对DICOM的IO支持,读取DICOM文件通常要借助vtkVolume16Reader来完成,但要涉及一系列复杂问题,我们使用如下示例说明:

[c] vtkVolume16Reader *Reader = vtkVolume16Reader::New(); Reader->SetDataDimensions(256,256); //图像尺寸 Reader->SetDataByteOrderToLittleEndian (); Reader->SetFilePrefix ("E:\ct"); //路径 Reader->SetImageRange(1, 93); //切片起始段 Reader->SetDataSpacing (0.8, 0.8, 1.5); //切片间距 [/c]

 另外,该方法也不支持对压缩数据或多帧影像进行IO操作。

 从vtk4.4起,一个直接针对DICOM文件读取的类被引入vtkDICOMImageReader,从而完全替代了vtkVolume16Reader的历史地位。vtkDICOMImageReader的重要改进在于,其直接支持DICOM,避免了许多没有必要的前置操作。

 http://www.vtk.org/doc/nightly/html/classvtkDICOMImageReader.html

 但在实际应用中vtkDICOMImageReader仍然无法满足需求,如不支持查看完整的meta file,也不支持压缩数据和多帧影像。

 为了全面支持DICOM 3.0标准,开发者必须借助外部组件辅助IO。我们在起初提出引入ITK是一种有效的改进方法,这里推荐另外一个重要的开源项目GrassrootDCM基层dicom库,简称GDCM。

 GDCM旨在对DICOM文件编码进行处理,提供DICOM标准中各类编码格式的相互转换操作,包括将各种文件编码转换为RAW原始数据文件。目前GDCM已经提供了针对vtk的DICOM文件IO接口,结合vtk和gdcm,我们就可以完全实现稳定的dicom文件IO操作了。

 但是将GDCM纳入现有工程项目中并非易事,我们将在后续文章中就gdcm做一些说明。

Comments

解析渲染系统

 本文的目的旨在对vtk的渲染系统做一简要概述,并引入一些示例。如果读者已经阅读过官方出品的System Overview,文中的示例对初学者来说仍然具有一定意义。

 vtk包含两个基层子系统:一个已编译的C++类库,以及一个解释封装层。后者可以使用户能够使用Java、Python以及Tcl语言引用已编译的C++类。

 在vtk中存在两个基本对象模型,图像模型和可视化模型。两个必要模型共同构成成了vtk的基本概念系统。

 1、图像模型

 图像模型包含了以下一些基本对象,这些对象共同组成了一个“场景”:

 vtkActor,vtkActor2D,vtkVolume—vtkProp和vtkProp3D的子类

 vtkTransform

 道具Props是指我们能在场景中看到的物体,在vtk中道具使用一个抽象类vtkProp或vtkProp3D表示。通过使用上述类的子类而生成的实例变量即“角色”。应当注意,道具本身并不直接表示其几何形状,而是通过引用映射器mappers表示图形数据。另外,还可以使用一种转换对象,这种对象内部封装的4*4转换矩阵可用于控制道具的位置、方位和缩放比例。

 vtkLight

  灯光用于表示和操作场景照明,且仅需要在3D场景中使用。在场景中灯光与角色的相互作用是控制绘制过程的一个主要因素,一旦光线与场景中的角色发生相对作用,我们就可以使用相机进行观察。在计算机图形学中,使用过多种不同类型的灯光,其中,最简单的一种是在无限远处的点光源,这就意味着它所照亮的物体接受的是一组平行的光线。而另外一种是在有限区域内的点光源,其照射在物体表面上的光线不再互相平行。另外我们假设在光线的传播过程中,其能量不发生损失,即其光线强度始终保持不变。把这样简化了的模型用在可视化过程中,使得我们对光的计算公式也获得了简化。场景中的灯光包括漫反射光、镜面光以及环境光。

 vtkCamera

 相机用于控制在渲染过程中三维几何体如何被投影到二维平面。相机通过几种不同方法实现定位、焦点和指向功能。此外,相机也用于控制透视投影和立体视图。

 vtkProperty,vtkProperty2D

 属性对象控制了一个道具的外在属性,如颜色、漫反射、环境以及镜面光效果等。

 vtkMapper,vtkMapper2D—vtkAbstractMapper的子类

 vtkLookupTable,vtkColorTransferFunction—vtkScalarsToColors的子类

 映射器通过结合vtkLookupTable,用于转换和渲染几何图形。映射器为可视化管线和图像模型之间提供了接口界面。而vtkLookupTable以及vtkColorTransferFunction则负责把数值映射为颜色,这是可视化技术中最为重要的技术之一。 

 vtkRenderer,vtkRenderWindow

 渲染器与渲染窗口负责管理图像引擎和计算机窗口系统的接口。其中渲染窗口是在计算机窗口中进行渲染的窗口。可以有多个渲染器同时在一个渲染窗口中工作,也可以创建多个渲染窗口。渲染器工作的区域称为视口viewport。

 vtkRenderWindowInteractor

 一旦把对象绘制进渲染窗口,就有机会进行数据交互了。VTK提供了多种和场景进行交互的方法,其中之一就是引用vtkRenderWindowInteractor对象,这是一种简单的工具可用于操控相机、选取对象、调用invoke用户定义的方法、进入/推出立体观察视角以及改变部分角色属性等。

 2、可视化模型

 图像管线的作用是将图形数据转换成图像数据。而可视化管线的作用则是将图像信息转换成图形数据。换一个角度来看,可视化管线负责构建图形几何表示,然后再利用图像管线将这种表示绘制在渲染窗口中。

 VTK使用了数据流的方式将图像信息转换成图形数据,在这种方式中,包含了两个基本类型的对象:

 数据对象vtkDataObject

 处理对象vtkProcessObject

 数据对象可以表示各种类型的数据,具有一定组成结构的数据被称作数据集dataset,数据对象由几何结构和拓扑结构(点和单元),以及相关的属性数据如标量或向量组成。属性数据是与数据集的点或单元相联系的。单元是多个点的拓扑构成,它是组成数据集的原子类型。 

 处理对象,即我们通常所说的过滤器filter,它被用于对数据对象进行操作并产生新的数据对象。处理对象表示了系统中对数据进行处理的算法。数据对象和处理对象连接在一起就构成了可视化管线。

 在可视化管线中,源处理对象是通过读取或者构造一个或多个数据对象而产生数据的对象。过滤器通过吸收一个或多个数据对象,经过处理后,输出一个或多个数据对象。映射器则是将数据对象转换成图像对象,然后由图像引擎进行渲染。

 3、一些问题

 下面讨论在构造可视化管线中的值得特别注意的一些问题。

 首先,管线拓扑可以使用多种方法构造,如:

 aFilter->SetInput(anotherFilter->GetOutput());

 上述语句是将anotherFilter过滤器中的输出再用于aFilter过滤器的输出(多重输入和输出也有类似的方法)。

 其次,必须制定一个关于管线运行的控制机制。通常我们只想运行管线的那些必要功能以获取输出,vtk引入了基于每个对象内部更正时间的惰性计算lazy evaluation(即只在数据被请求时进行计算)模式。

 第三,管线的装配要求每个对象必须互相兼容,以适应SetInput()和GetOutput方法。在vtk中,c++程序会在编译时类型检查过程中检查此类问题,而对于解释型语言只能在运行时从解释器报错中发现问题。

 最后,必须决定是否在管线运行时使用缓存,亦或维持数据对象。

 4、管线执行概览

 前文已经提到,vtk可视化管线只有当请求数据计算时才会运行(惰性计算)。例如,如果用户实例化了一个Reader读取器对象,并随后请求返回象素点数GetNumberOfPoints,读取器对象将会通过该方法返回“0”,尽管事实上数据文件可能包含了数以千计的象素点。然而,如果在调用GetNumberOfPoints方法前加入一句:

 reader->update();

 读取器对象就会返回正确的象素点数目。出现这种情况的原因是,在前例中GetNumberOfPoints方法并不请求计算,对象仅仅返回当前的象素点数,首次计算前显然为“0”。而update()方法的作用即是强制运行管线,从而强制读取器从相关文件中读入数据。

 通常情况下,用户不需要manually手动调用update(),因为过滤器是接入可视化管线的。也就是说,当角色接收到重新渲染得请求之后,它会将相关方法转发至映射器,同时update()方法就被自动送入了可视化管线中。从较高层次来看,render()方法通常初始化对数据的请求,该请求再通过管线传递,此过程中管线待更新部分的过滤器将重新运行,从而保证了管线末端的数据是最新的。

Comments

次日依然悲剧

 可以预见,这也许会是本版的倒数第二篇文章了。

 有时候真的很担心场外因素介入到正常游戏规则里,然而它还是不可避免地发生了。但是最终的结果却让人感到一些欣慰,或许应该说是庆幸。

 感谢所有人。

Comments

首日悲剧

第一天就悲剧了。

Comments

最后一周

 再过一周就要正式录取了,到那时就已较当初决定读研过去了一年时间,复习开始到现在也有9个多月了。我一再提醒自己要重视过程,却没想到是因为结果往往出人意料。

 浩然兄说我当初就应该会后悔,仔细想了一下,确实还从未因为这事儿后悔过。因为这件事从三个月前起本来就远未达到我设想的安全概率,最后倒不如说是万幸。

 但是我的确没有办法使高高在上的人产生丝毫信任感,在我看来评价可以从简单的日常交谈到知识的厚积薄发,事实上它的复杂程度要比我想象中大得多。

 于是就突然又感到有些后悔,想方设法取得信任,这几乎从来都不是我所关心的事情:因为我当然信任我被信任的,而他应具备识别我可以被信任的能力,或者会用一些手段(当然凡是合理的要求我都会接受),否则我怎么能反过来信任他呢?

 记得一位哲学老师在启蒙课上引用了“哲学,就是疯子和傻子的对话”这句经典来描述哲学,问题是人们往往认为自己聪明,剩下的就只有贫穷的哲学工作者了。在追求“智慧”的道路上,已经产生太多悖于真理的观念,但我们根本无法和历史对抗。于是只能安慰自己说“与其想方设法取悦于人,倒不如努力做好自己”。

 我真觉得这些已经不重要了。

Comments

WordPress 3.0beta1 Arrived!

 伟大的WP在北京时间3日夜间抢先发布了里程碑式的3.0 beta1,此次更新包括了Custom Menu、WP/MU merge等我们一贯关注的内容(这也是我们日常促进程序自定义化的重点内容)。

 从test things上来看,新的缺省主题2010将支持自定义背景图片和页眉选项,对我们这些希望保持WP一贯风格的伪劣designer来说,真正支持傻瓜式DIY风格也是不错的思路。

 另外,3.0中会提供一个代码级功能,即Custom Post Types。从介绍来看这一功能仅仅是一个进行基本Types分类的便捷工具,熟悉tumblr的用户可能会乐于享受这种相当程度上的自动化。不过Kovshenin向我们展示了该扩展更为广阔的前景,WP在未来的持续扩张似乎已经不可避免了。

 下面是关于本文的一些链接:

 http://wordpress.org/development/2010/04/wordpress-3-0-beta-1/

 http://kovshenin.com/archives/custom-post-types-in-wordpress-3-0/

 对于我们来说,目前尚无足够的精力来全力体验和测试该早期beta版本,因此希望很快就能有更加稳定的版本释出。

 还有,别忘了我们的接头暗号:Touch it, Squeeze it, Turn it, Flip it!

Comments