就要毕业了

28号,全体滚蛋……今天我倒是提前把大多数的东西的搬回家了。我没有卖书的习惯,现在还有1995年的电脑报的合订本,除了一些实在不想用的教科书卖了以外,很多杂志都保留着,这次的数好多书啊,垒起来都有4米多高,两个好友帮我搬了一些到车上,爸爸开车送回来的。回来了发现没有地方放书了,书架已经塞满了,没地方放了……~

还有十多天功夫,4年的同学就要离开了,少数的留下读研,更多数的是奔赴工作岗位,正式跨入社会了。很难想想在十天后的心情,抑或是高兴抑或是悲伤。时间依然向前,大学生活也便成为了历史。当毕业生离校手续表拿到手里的时候,感觉总是那样的别扭。偶尔打开抽屉看到高考录取通知书的时候,仿佛觉得我才来学校,然而就没有几天就要离开了,时间真是快啊。

遗憾自己的文采很次,没法写的那样的感人和蓝调。上个星期把相机带到学校了,不知道在最后,能用相机记录下些什么呢?

这几天玩游戏

论文写完了,PPT做完了,程序不想写了,无聊了,就玩游戏了~

装上最新的“蜘蛛侠3”游戏,玩了3天时间,9个多小时基本上就搞定了。画面质量还算中等,令人印象比较深刻的是其大量使用的凹凸贴图,爬到墙上的时候就会发现纹理很清晰,怪不得这个游戏最低配置是Geforce 6系列的,在我这个6600GT上只能开800X600其他全低。但是其实开到最高也没有感觉游戏画面有多少的进步,反而是帧数下降得相当厉害。落后拉~

蜘蛛侠3的动作做的挺好的,操作也比较容易上手,前提是图像要流畅……~要不然一吐丝,一个转向,人都不知道飞到哪儿去了……整个游戏玩下来基本上还是保持在20帧附近吧,很多场景的相当之不流畅,唉。之前有一个化学工厂的场景,也就是一秒钟一幅画的水平,也没有觉得画面有多么的复杂。开一个闸门的时候,望着远处的城市我就心酸啊,1秒钟一幅画,我开闸要开到何时啊!重试很多次以后终于放弃了。换了最新的94.71驱动,进去玩,结果就对了。

打沙怪的时候才心烦,第一次哈瑞打沙怪的时候就是一帧一帧的像是放幻灯片,然后这个时候还要你一系列的按键……如果按错了,还得从头再来……!!天啊,简直就是折磨人啊!后来一怒之下把驱动程序换成了NVIDIA给测试人员玩的驱动,结果……基本上还可以玩了,应该说是基本流畅的玩!!!玩个游戏换了两次驱动…………………………

最后通关之前和毒蜘蛛玩的时候才造孽啊,好卡啊,动作都不到位,基本上保持在5幅画面每秒吧…………

终于还是通关了,卸载了,再也不玩了,虽然情节很棒,可是……真不如看漫画。

卸载之后又把最新的古墓丽影10周年纪念版给装上了,太搞笑了,4个G的游戏,结果基本剧情和一代差不多,隐隐约约都有印象的,图像我就不说什么了,劳拉看来也是真的老了,还不如老的一代,真是悲哀啊,EIDOS估计再也拿不出什么好玩的玩意儿给人了吧!20分钟时间,体验了第一个关卡就把它删除了,实在是无聊…………………………

这下没有游戏玩了,不玩了,该研究什么研究什么去

OpenSceneGraph 笔记--C++/CLI写托管Scene类

最近学了C++/CLI,也写了一些小玩意儿体验了它的强大,昨天开始筹划将以前的弯管机的模拟程序用C++/CLI重写。

基本思路是将底层3D部分和上层GUI图形界面部分大体分离。最原始的做法是写一个C++的类,然后定义一些接口,然后用C++/CLI写一个Wrapper,然后用C#进行调用。这种做法其实不是很好,增加了很大的工作量,而且在写Wrapper的时候难免有很多重复性的赋值代码。

第二种思路就是直接用C++/CLI开始写,将Native部分和Managed部分合并在一块儿写。当然C++/CLI有一些限制,不能在托管类里面直接嵌套非托管类,只能有非托管类的指针等等。这个限制带来的最大的不好是osg::ref_ptr,也就是OpenSceneGraph里面的智能指针无法使用了,因为他是一个类型,不能直接嵌入到托管类里面,所以类似下面的语法是错误的:

ref class ManagedClass
{
osg::ref_ptr node;
}

当然这样写是正确的:

ref class ManagedClass
{
osg::Node* node;
}

但这样就失去了智能指针的保护,很容易造成内存泄露,所以当务之急是需要写一个智能指针来代替osg::ref_ptr,但基本上要保持功能的不变。OpenSceneGraph的引用类都是继承与osg::Object,而osg::Object又是继承于osg::Reference。所以这些引用类都有ref()和unref()方法,用于增加和减少ReferenceCount,当ReferenceCount=0时,就自动delete了。

参考osg::ref_ptr并去掉这个类中不常用的部分,写了一个smart_ptr类,完成了智能指针的任务:

//! OpenSceneGraph managed smart_ptr.
template
public ref class smart_ptr
{
public:
typedef T element_type;

smart_ptr() : _ptr(0) {}
smart_ptr(T* ptr) : _ptr(ptr) { if (_ptr) _ptr->ref(); }
smart_ptr(const smart_ptr% rp) : _ptr(rp._ptr) { if (_ptr) _ptr->ref(); }

~smart_ptr() { if (_ptr) _ptr->unref(); _ptr = 0; }

smart_ptr% operator = (const smart_ptr% rp)
{
if (_ptr==rp._ptr) return *this;
T* tmp_ptr = _ptr;
_ptr = rp._ptr;
if (_ptr) _ptr->ref();
// unref second to prevent any deletion of any object which might
// be referenced by the other object. i.e rp is child of the
// original _ptr.
if (tmp_ptr) tmp_ptr->unref();
return *this;
}

inline smart_ptr% operator = (T* ptr)
{
if (_ptr==ptr) return *this;
T* tmp_ptr = _ptr;
_ptr = ptr;
if (_ptr) _ptr->ref();
// unref second to prevent any deletion of any object which might
// be referenced by the other object. i.e rp is child of the
// original _ptr.
if (tmp_ptr) tmp_ptr->unref();
return *this;
}

//T% operator*() { return *_ptr; }
T* operator->() { return _ptr; }
T* get() { return _ptr; }

bool operator!() { return _ptr==0; } // not required
bool valid() { return _ptr!=0; }

T* release() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp; }

private:
T* _ptr;
};

如此这般折腾以后,终于可以在托管类中间使用智能指针了:

public ref class Scene
{
protected:

smart_ptr gc;
smart_ptr root;
smart_ptr viewer;
smart_ptr camera;
....

跨越了智能指针的障碍以后,还有很多问题有待于解决。像osg::Vec3这些常用类只能重写以便于调用。像查找节点FindNode这种函数:

ref class NodeFound
{
public:
String^ name;
smart_ptr osgNode;
};

NodeFound^ FindNode(String^ name)
{
FindNodeVisitor findNodeVisitor;
findNodeVisitor.name=MarshalString(name);
root->accept(findNodeVisitor);
if(findNodeVisitor.node==NULL) throw gcnew Exceptions::NodeNotFoundExpection();

NodeFound^ nodeFound=gcnew NodeFound();
nodeFound->name=name;
nodeFound->osgNode=findNodeVisitor.node;
return nodeFound;

return nullptr;
}

只能定义一个新的结构作为返回值,否则C#语言无法使用,因为它不能解析一个智能指针。……或许,还有别的方法可以用吧,比如用IntPtr这种,但可能又会脱离了智能指针的保护,变的危险起来。