VRPN 介绍及使用
Virtual-Reality Peripheral Network ( VRPN )由一系列的类库组成,它也提供一系列的服务在虚拟现实系统中实现应用程序与外围物理设备( tracker 等)之间的网络透明接口。
VRPN 提供:
V RPN 的目标不是提供一套全面的 VR API , VRPN 专注于为尽量多的设备提供统一的接口,实现网络透明访问设备的低延迟和可靠性。
不难想象 VRPN 不是为一套设备提供驱动程序,而是为一套功能提供接口。特定的设备属于一个或多个标准设备类型。每种设备类型指定一致的接口和语法通过设备实现这些功能。常用的设备列在下面。有新的设备类型提供就可以建立新的类型。
映射一系列设备到一个标准设备,需要映射每个设备的不同功能到同一个接口。是提供一个简单的接口还是提供一个功能齐全的接口是个两难的决定。 VRPN 通过以下解决:
实例解析:一个特定的设备可能实现不止一种的功能。一个该设备的 VRPN 驱动程序输出多种设备类型的接口。 SensAble™ Technologies Phantom™ haptic display 的服务器在相同的设备下输出 Tracker, Button, 和 ForceDevice 三个接口 . 客户端处理 Phantom™ ,好像是三个设备各自提供各自的功能。虽然在 Phantom™ 系统中 Tracker, Button 和 ForceDevice 设备在逻辑上时分开的,但是为了更有效的通信,在内部它们是一起被映射到相同的网络连接。
功能分解让应用程序在不同的输入 ¥ 输出设备移动变得容易。客户端程序不用变就可实现在不同 VR 设备之间的移动。
以 Windows 系统 VS2005 为例,其他参见 http://www.cs.unc.edu/Research/vrpn/index.html
实例: DTrack 跟踪设备
#include
#include
#include
//回调函数, vrpn_tracker 下有很多的回调函数,可以实现对各种数据的处理,//这里只是 以 得到位置和方向信息的 回调函数为例。
void VRPN_CALLBACK handle_tracker(void *userdata, const vrpn_TRACKERCB t)
{
printf("handle_tracker/tSensor %d is now at (%g,%g,%g)/n",
t.sensor,
t.pos[0], t.pos[1], t.pos[2]);
}
int main(int argc, char *argv[])
{
vrpn_Tracker_Remote *tkr;
// 打开跟踪器
tkr = new vrpn_Tracker_Remote(" DTrack @ localhost ");
// 设置回调函数
tkr->register_change_handler(NULL, handle_tracker);
// 主循环
while ( ! done ) {
//得到更新数据并调用相应回调函数
tkr->mainloop();
}
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int i = 0;
osg::Quat rota;
osg::Vec3 pv;
void VRPN_CALLBACK handle_tracker(void *userdata, const vrpn_TRACKERCB t)
{
rota.x() = t.quat[0];
rota.y() = t.quat[1];
rota.z() = t.quat[2];
rota.w() = t.quat[3];
pv.x() = t.pos[0] * 20;
pv.y() = t.pos[1] * 20;
pv.z() = t.pos[2] * 20;
}
int main(int argc, char *argv[])
{
vrpn_Tracker_Remote *tkr;
tkr = new vrpn_Tracker_Remote("DTrack@localhost");
tkr->register_change_handler(NULL, handle_tracker);
osg::ArgumentParser arguments(&argc,argv);
// initialize the viewer.
osgViewer::Viewer viewer;
// load the nodes from the commandline arguments.
osg::Node* model = osgDB::readNodeFile("cessna.osg");
if (!model)
{
return 1;
}
// tilt the scene so the default eye position is looking down on the model.
osg::MatrixTransform* rootnode = new osg::MatrixTransform;
rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees( 30.0f ), 1.0f , 0.0f , 0.0f ));
rootnode->addChild(model);
// run optimization over the scene graph
osgUtil::Optimizer optimzer;
optimzer.optimize(rootnode);
// set the scene to render
viewer.setSceneData(rootnode);
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
viewer.realize();
osg::Quat r;
while (!viewer.done())
{
tkr->mainloop();
rootnode->setMatrix(osg::Matrix::rotate(rota) * osg::Matrix::translate(pv));
viewer.frame();
}
return 0;
}
运行结果:通过跟踪物体改变,改变应用程序中飞机的位置和旋转变化