毕业了,前天和朋友们一起来杭州逛一逛,天宫不作美的是当天风雨大作,只好白天逛逛杭州的市中心。和武汉一样,商场里价格不菲的各种衣服,奢侈品,同学笑称:杭州的大洋和新世纪。
晚上雨不再那么大了,朦朦细雨中夜游西湖。刚被洗刷过的西湖,水面不是那么平静两岸相差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()) ;
(完)
做了一个多月的毕业设计,今天实验室例会上给老师做了个报告,同时悲痛的得知这个难得的暑假估计大半时间要贡献给实验室了
今天报告的PPT
视频演示 : 清晰版 (On youtube)
在C++中一个类的友元函数或者友元类可以实现访问该类私有变量或者方法。但是对于静态方法使用声明友元类的方法却不能如愿,例如:
class Bar ;
class Foo {
public :
// do some custom initialize
static Bar *GetBar() { return new Bar() ;}
};
class Bar {
private:
Bar(){ }
// friend class Foo ; will cause the compile error
friend Bar *Foo::GetBar() ;
} ;
从上面的例子可以进一步理解类的静态成员的含义:属于类的上下文中,而不绑定于特定的对象(即无隐含的this指针)。
看着旁边的倒计时条,马上10.04就要发布了,虽然早就开始用beta的但是正式版的到来还是让人感到有点小兴奋,这几天ubuntu的升级也更加频繁了。
中午读googlereader时候看到皓哥写了篇博客,突然觉得心里空了一下。
以前大家都在一起有说有笑,转眼就各奔东西了,而且生活仿佛回到了高中的时候,简单到单调,每天两点一线之间不知道为了什么奔波。还记得以前每天的饭量相当于现在一的顿饭(老妈知道了肯定高兴),其实不是能吃了,是真的饿了……
还记得高中时物理老师总告诉我们生活是美好的,有点抽象了,我觉得向照镜子,当你微笑时生活也在对你微笑。
不要问我永远有多远,我真的不忍心告诉你:不到三年了。
现在要做的就是饱满激情,想着理想前进前进前前进。
好久没有更新博客了,最近比较忙,头绪也很多。
其实对于this指针的使用,我个人一直是倾向于对于成员函数以及成员变量都明确使用”this”指针。今天在阅读 unladen-swallow 的 StyleGuide 时,项目也明确提出了Always use this的说法,并且用C++ 在名字查找时使用 two phase parse的方法引发的问题,很有针对性的指出了使用this指针的好处。下面直接引用过来,也好提醒自己继续保持这个习惯
[35.19] Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?
Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:template<typename T> class B { public: void f() { } //member of class B };template<typename T> class D : public B <T> { public: void g() { f(); //bad (even though some compilers erroneously (temporarily?) accept it) } };This might hurt your head; better if you sit down.
Within D::g(), the name f does not depend on template parameter T, so f is known as a nondependent name. On the other hand, B is dependent on template parameter T so B is called a dependent name.
Here’s the rule: the compiler does not look in dependent base classes (like B) when looking up nondependent names (like f).
This doesn’t mean that inheritance doesn’t work. Class D is still derived from class B, the compiler still lets you implicitly do the is-a conversions (e.g., D* to B*), dynamic binding still works when virtual functions are invoked, etc. But there is an issue about how names are looked up.
Workarounds:
Change the call from f() to this->f(). Since this is always implicitly dependent in a template, this->f is dependent and the lookup is therefore deferred until the template is actually instantiated, at which point all base classes are considered.
Insert using B::f; just prior to calling f().
Change the call from f() to B::f(). Note however that this might not give you what you want if f() is virtual, since it inhibits the virtual dispatch mechanism.
同时在9.4.2 Dependent Base Classes一节中也提到过这种dependent和nondependent的规则,其中一句话说到:
Hence, the C++ standard specifies that a nondependent name appearing in a template is looked up as soon as it is encountered.