看了上一篇,一年过去了,再一次停了很长时间,总觉得过去的还是不能就真的过去了,还是要停下来想一想,整理一下。今天Kinect fitting room有点小进展,借着更新校内上一篇日志的机会重新拾起博客。
下面的内容都是从我校内贴过来的,虽然依然有偷懒的嫌疑,不过终究是动了。
———————–我是分割线——————————————————–
10.18日更新
首先是一个和流体没什么关系的,业余时间用kinect做的一个试衣,咱也穿了回裙子⋯⋯ORz
最近正在做的编辑器,继承了之前写的绘制引擎,集成了Bullet2.79支持OpenCL和Cuda,目标是把sph仿真加进来,并且实现粒子和mesh的交互,支持fixed, forward, deferred和light pre-pass管线,支持order independent transparence。
简单的编辑器,作为之前工作的总结,不过绘制没有更新,因为准备用上边的新编辑器代替
重写了Renderer,在原有引擎基础上设计了一个postprocess framework,把折射反射都作为post effect,不必单独处理了
刚才开会前录的 Refraction, caustics and shadows
上周录的 Refraction and shadows
在自个本子上做的原型,显卡不给力,Refraction, caustics and shadow
最早的,企图让它可交互,不过不现实 progressive photon mapping
to be continued…
九月开学了,开始了研究生生涯
刚开学这段时间,假期比较多,也有很多的时间到实验室,至于实验室是个什么地方,不解释。
九月看了《盗梦空间》还做了一系列梦,对我们现在的生存环境的真实性表示怀疑,也难怪,当下真真假假虚虚实实,看了twitter还要用“新闻联播”来疗伤。
月底双节齐至是个促进消费的季节,就在中秋前我得mac和ipod touch都到了所以中秋节除了和央财的女生秋游了一天其余时间都陪我的mac了。
这段时间我竟然越来越感觉现代人的社交圈越来越广,生活圈却越来越小了,凡事都有些浮躁求快,很想静下心来做点什么,结果一系列紧急的事搞的反而什么都没有做成,每天拖着疲倦的身体回寝室睡觉。而这些都是我不喜欢的。
十月了,到双十节前是十一,30号的时候去吃了巫山烤鱼然后远足到鸟巢,算是一个月来最放松的几个小时了吧,但不知道是否这种机会还能长久。
原本今天打算配我校外国语女僧出去玩,结果发现男女比严重超过北航平均水平,所以果断脚底抹油,把这难得的机会留给那些寂寞男吧。不过,说回来,谁不寂寞?
最近几篇博客都发些牢骚,没什么技术或者学术的东西可以拿出来分享,这是因为我觉得图形学之流水太深了,虽然自己没有一刻放松学习,但是离初窥门径尚且距离甚远又岂敢出来班门弄斧。花放到这里希望能激励自己再接再厉,有昭一日可以拿点出手的东西和看官们分享。
9月9号报道的,但是那天没什么时间,也不想在那个特殊的日子写点什么……
昨天学院开学典礼,晚上英语分班考试——免修班、A班、B班,好久没有考试了,觉得没什么感觉,也不知考的怎么样。今天上午学校的开学典礼,和学院的一样走个过场,甚至还没学院的有意思。
总之就这样循规蹈矩中,我的硕士研究生的生涯算是正式拉开了序幕……
未来是怎么样?
You never know yourself
大项目中期检查还有一个星期就要开始了,实验室里大家都在紧张的准备着。今天打开自己的博客,发现居然没有七月的achieve。
七月,一个美好的月份就这么凭空消失了,至少在这里找不到它的踪迹,这多少然人感到沮丧,于是我开始寻找七月的记忆,在八月八日把他们记录下来,顺便提醒自己不要再错过其他的月份。
1号的下午,坐火车从杭州回北京,那天天气很热,不知是不是杭州用温度极力驱散我们这群过客换得一时清静,反正我是一刻不想在这火炉子里锻炼了。第二天早晨到的北京,正如我车上所想的那样,北方的早晨要凉爽些,我深吸了一口清晨的灰尘奔赴寝室。接下来几天比较清闲,换了个寝室,从18栋换到了6栋,条件也比以前好多了,离着实验室也更近了。那段时原本想上来写篇日志,想大多数人一样抒发下旅途的感想,但苦于不知从何谈起也就搁浅了,后来就一直到今天,如果再然我谈浙江之行的感觉,我已全然谈不出了,仿佛已经融入我的意识,它就在那里。
看上去,七月的开始是清闲的,但这不意味着整个七月就像我一直认为的那样是假期的日子。在一次中期动员后终于进入状态了:每天的作息差不多是9:00到00:00,13号27号分别去了趟西安和上海出差。上海那次是当天去当天回,据说我们的车路过SB园,不过显然那个时候我觉得睡觉比SB更吸引我,毕竟SB天天有。这段时间虽然忙,但忙的很规律,项目在那次动员会过后也神奇的前进了不少,中期在即各种问题似乎也都要解决了。
在做项目时写了一个插件框架,是个个人项目,我叫它Yaps(Yet Another Plugin System),也算是为项目后期个架构做个实验,目前版本已经比较稳定了,之后考虑开源,放出来溜一溜。Yaps是Header File Only的轻量级插件框架,目前就Windows平台上的编译器Msvc6~10、Mingw而言,编译出来的插件是可以公用:创建导出类的对象,以及对象生命周期的维护,基本达到了独立于编译器的目标,下一步准备着移植到linux下,当然,我并没有打算做的如DnyObj那样做到插件的跨平台,只是想在linux下使用而已。
在忙里偷闲的时候把Effective Go看完了,觉得Go的风格正是自己期盼和喜欢的那种,是个神奇的语言,但愿能长久,不要像D那样一闪而过。我也有考虑,用Go写点东西,应该至少要比C++来的快些。此外,编译和尝试了许多library:GLFW、SDL、JsonCpp、PyhonQt、MyGUI、CEGUI、glv、Horde3D。特别值得一提的是Hord3D这个渲染引擎,很小巧,但却号称是下一代渲染引擎;更重要是他的philosophy只作一件事情,它的目标是作为其他项目的组件,你不必为使用Horde3D做其他额外的事情,拿来用就好,这也是我这么些年一直努力去做的事情,所以很有兴致的把它代码拿来读一读,如果拿读书来比喻,刚刚读完了它的序言,不过相比一些巨型项目来说还是读的完的,希望他能有更多引人入胜的情节。
好了,就写到者,去祭下五脏庙去。
Good day.
毕业了,前天和朋友们一起来杭州逛一逛,天宫不作美的是当天风雨大作,只好白天逛逛杭州的市中心。和武汉一样,商场里价格不菲的各种衣服,奢侈品,同学笑称:杭州的大洋和新世纪。
晚上雨不再那么大了,朦朦细雨中夜游西湖。刚被洗刷过的西湖,水面不是那么平静两岸相差1000年,古今文化在这里碰撞交融,雷峰塔夜里灯火流光格外刺眼,断桥上中仿佛出现古老的传说,让人有种想把感情都扔到西湖的冲动。
西湖纵然美,但过于公园化了,对摄影技术很菜的我来说,相机捕捉到得更多是人影。本来第二天想继续游览西湖其他人文景观,但听说还有可能下雨,所以就提前跑到西塘了。
我们住在河边的客栈,推开窗子古镇便引入眼帘,寰秀桥就在不远处看着客栈的观景台,坐在藤椅里吹着河。树、水、楼阁都摆好了pose随处取景便是幅画,和其他走马观花的游人一样,我们都是不是画面中的元素。到了夜里,西塘就想把自己藏起来了,卡片相机不中用了,只能用眼睛收藏这景色。泛舟在河上,安静的河面热闹的岸边,西塘好像在抱怨人们打扰了她千年的静谧。从河面上不停的闪光灯可以看出游人们都想留住眼前也色,但夜究竟是黑的,任凭你如何闪他依然在那里不为所动,一次一次打击着拍照的人们,可是人就是人,依然固执得闪着,夜的疏影就这样成了光的琉璃。
It’s a long time since my last updated. These days I was immersing in alcohol for celebrating our graduation. I was filled up with too many complex feelings to spilled out. The day after tomorrow I will receive my diploma and draw an end to my undergraduate life.
I write down this short post as a remark of the new beginning of my student life as well as a reminder of my best memories that elapsed.
饮酒歌
——昨日饮酒后,寝室小白同学兴起而做
幽幽月,声声乐,酒酣意浓心无却;
杯杯错,句句愁,苦短情长岁无愁。
乐以人间丝竹之天籁,难以言觥筹之清越;
晓以清风雨露之精华,亦非喻歧路之情殇。
征战沙场十余载,天意使然意相逢;
同窗四年苦与乐,天地造化神使然。
纵岁月之流逝,折戟之沉沙,沧海之桑田,世事之变幻;
然亘古之情义,越光阴之禁锢,展梦想之天翼,谱情义之永殇。
饮酒歌,饮酒歌,苦痛饮,乐无求;
歌吟酒,歌吟酒,醉舞月,人间游。
空意空,空满楼,人去楼空月泪流;
愁亦愁,几多愁,花自飘零水东流。
今天早起的火车到了武昌。
武昌这正朦朦下着小雨,不热也不清爽,有点闷,像极了当时的心情。
这次回来主要是为大学生涯画上个句号,离别总是愁的,亲爱的同学们,生活一起四年了,下个月一过大家都各奔东西,不知何时才能相聚,所以让我们珍惜这“最后”的日子吧。
不过,在享受大学最后时光的日子前,还要把毕业论文这个遭天杀的事情弄完,一回宿舍谈论的便是这令人抓狂的事情。我相信苦尽甘来,论文呢这点点“小苦”过后一定是兄弟们开心的畅饮“来来来,干了这杯还有第二杯”……
今天毕设代码暂时算告一段落了,在上次中期的基础上加入了Phantom desktop的接入,提供触力觉反馈。其中触力觉反馈使用的是OpenHaptic的HDAPI
为了提供Haptic的支持主要解决2个问题
- Phantom设备的ServoLoop 1khz的力渲染与VTK15~30帧的图形渲染
- Phantom设备坐标系与VTK世界坐标系的匹配
关于问题1有两种解决的方法:
- 由于VTK的对象实现了subject/observer的模式,所以可以添加一个observer
- 使用Timer每间隔一段时间同步设备状态,渲染图形
由于UI是用QT实现的,所以VTK并不能自己处理重绘事件,所以这里选择了第2种方法,设置timer。在此之前曾尝试使用单独的绘制线程,但是由于VTK和OpenHaptic单独管理各自线程并且机制不同,无法在合适的时间同步设备状态,所以便用timer,这样使得图形渲染在同意线程中执行,也符合逻辑。
关于问题2
通过HDAPI可以获得探针姿态变换矩阵,利用HDU里的
void hduMapWorkspaceModel(const HDdouble *modelMatrix,
const HDdouble *projMatrix,
HDdouble *wsModelMatrix);
可以获得设备坐标系到世界坐标的变换,唯一要注意的是VTK内部矩阵是左乘,而OpenHaptic和OpenGL一样是右乘。
下面的代码片段描述了获得变换矩阵的方法
// get current render window vtkRenderer *ren = this->renderer_ ; // calculate the aspect from render window double aspect[2]; ren->ComputeAspect(); ren->GetAspect(aspect); double aspect2[2]; ren->vtkViewport::ComputeAspect(); ren->vtkViewport::GetAspect(aspect2); double aspectModification = aspect[0]*aspect2[1]/(aspect[1]*aspect2[0]); // get view port int viewport[4] ; ren->GetTiledSizeAndOrigin( // width viewport + 2, // height viewport + 3, // lower left x viewport, // lower left y viewport+1 ) ; // get the projection matrix vtkSmartPointer projection = vtkSmartPointer::New(); projection->DeepCopy(this->renderer_->GetActiveCamera() ->GetProjectionTransformMatrix( aspectModification*(viewport[2]/viewport[3]), -1.0, 1.0)) ; projection->Transpose() ; // get model view matrix vtkSmartPointer modelview = vtkSmartPointer::New(); modelview->DeepCopy(this->renderer_->GetActiveCamera() ->GetViewTransformMatrix()) ; modelview->Transpose() ; // Compute the transform for going from device coordinates to world // coordinates based on the current viewing transforms. ::hduMapWorkspaceModel(modelview->Element[0], projection->Element[0], this->workspace_model_) ;
下面的片段描述了如何利用获得的矩阵调整绘制视图中指针的姿态和位置。需要注意的是,变换之后会包换缩放的信息,如果不希望指针被莫名奇妙的缩放的话,需要去除缩放分量,可以使用vtkTransform类完成。
IHapticDevice::IHapticDeviceState *state =
this->device_in_graphic_->getCurrentState() ;
vtkSmartPointer workspace_model = vtkSmartPointer::New() ;
workspace_model->DeepCopy(state->getParentCumulativeTransform()) ;
workspace_model->Transpose() ;
vtkSmartPointer device_transform = vtkSmartPointer::New() ;
device_transform->DeepCopy(state->getTransform()) ;
device_transform->Transpose() ;
vtkSmartPointer device2view = vtkSmartPointer::New() ;
// set to the post multiply
device2view->PostMultiply() ;
// transform in work space
device2view->Concatenate(device_transform) ;
// transform to VTK view
device2view->Concatenate(workspace_model) ;
// set user transform
this->cursor_->SetPosition(device2view->GetPosition()) ;
this->cursor_->SetOrientation(device2view->GetOrientation()) ;
(完)
