OSG两个独立的相机观测
目标
在场景中创建两个视口。其中一个用于从坦克驾驶员的视角观察场景。该视口将被渲染于屏幕的上半部分。第二个视口由缺省的osgViewer::Viewer类接口(轨迹球,飞行等控制器)控制。它将被渲染于屏幕的中下部分。
概述:
OSG向开发人员提供了各种的抽象层次接口。前面的教程讨论的主要是一些较高层级的接口应用:例如使用Viewer类来控制视点,场景,交互设备和窗口系统。OSG的优势之一,就是可以允许开发者在使用高层次的接口的同时,访问较低层次的抽象接口。本章将使用一些低抽象层级的功能,对视点进行控制,并使用相应的类渲染场景。
代码:
为了创建两个视口,我们需要提供两个独立可控的摄像机。与OSG 1.2版本中所述不同的是,本例中将不再使用Prodecer::CameraConfig类,而是将多个不同的视口添加到组合视口 CompositeViewer类当中。下面的函数即用于实现添加视口并设置其中的摄像机位置。
void createView (osgViewer::CompositeViewer *viewer,//查看器,一个相框
osg::ref_ptr<osg::Group> scene,//场景
osg::ref_ptr<osg::GraphicsContext> gc,//显示设置定义相框的大小,View和Viewr在屏幕上的大小,位置
osgGA::TrackballManipulator* Tman,//放置相机的位置
int x, int y, int width, int height)//视口的大小,从多大的窗口看场景
{
double left,right,top,bottom,near,far, aspectratio;
double frusht, fruswid, fudge;
bool gotfrustum = true;
// 向最终的组合视口添加一个新的视口,并设置其操控方式。
两台独立的相机观测 此博文包含图片 (2012-07-11 08:57:41)转载▼
标签: 杂谈 分类: StudyNotes
目标
在场景中创建两个视口。其中一个用于从坦克驾驶员的视角观察场景。该视口将被渲染于屏幕的上半部分。第二个视口由缺省的osgViewer::Viewer类接口(轨迹球,飞行等控制器)控制。它将被渲染于屏幕的中下部分。
概述:
OSG向开发人员提供了各种的抽象层次接口。前面的教程讨论的主要是一些较高层级的接口应用:例如使用Viewer类来控制视点,场景,交互设备和窗口系统。OSG的优势之一,就是可以允许开发者在使用高层次的接口的同时,访问较低层次的抽象接口。本章将使用一些低抽象层级的功能,对视点进行控制,并使用相应的类渲染场景。
代码:
为了创建两个视口,我们需要提供两个独立可控的摄像机。与OSG 1.2版本中所述不同的是,本例中将不再使用Prodecer::CameraConfig类,而是将多个不同的视口添加到组合视口 CompositeViewer类当中。下面的函数即用于实现添加视口并设置其中的摄像机位置。
void createView (osgViewer::CompositeViewer *viewer,//查看器,一个相框
osg::ref_ptr<osg::Group> scene,//场景
osg::ref_ptr<osg::GraphicsContext> gc,//显示设置定义相框的大小,View和Viewr在屏幕上的大小,位置
osgGA::TrackballManipulator* Tman,//放置相机的位置
int x, int y, int width, int height)//视口的大小,从多大的窗口看场景
{
double left,right,top,bottom,near,far, aspectratio;
double frusht, fruswid, fudge;
bool gotfrustum = true;
// 向最终的组合视口添加一个新的视口,并设置其操控方式。
//View是一个显示窗口
osgViewer::View* view = new osgViewer::View;
//在查看器中加入显示窗口
viewer->addView(view);
//显示窗口设定自身相机的位置
view->setCameraManipulator(Tman);
// 设置视口的场景数据,并设置摄像机的截锥坐标。
//指定场景
view->setSceneData(scene.get());
//指定视口的大小,通过个窗口的大小来查看场景,也就是相片的大小
view->getCamera()->setViewport(new osg::Viewport(x,y, width,height));
//指定相机的焦距
view->getCamera()-> getProjectionMatrixAsFrustum(left,right,
bottom,top,
near,far);
if (gotfrustum)
{
aspectratio = (double) width/ (double) height;
frusht = top - bottom;
fruswid = right - left;
fudge = frusht*aspectratio/fruswid;
right = right*fudge;
left = left*fudge;
view->getCamera()-> setProjectionMatrixAsFrustum(left,right,
bottom,top,
near,far);
}
//指定相机中的图像在屏幕上的显示方法,与系统相关
view->getCamera()->setGraphicsContext(gc.get());// 添加渲染状态控制器
//这个控制器,控制图的光照,材质等
osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator;
statesetManipulator->setStateSet(view->getCamera()->getOrCreateStateSet());
view->addEventHandler( statesetManipulator.get() );
}
现在我们已经有了设置摄像机的函数,在仿真的其余部分中,我们将不再赘述有关基本场景建立(包括一个地形模型以及在其上运动的坦克)的内容。相关的代码可以从源程序中获取。我们需要对坦克模型添加一个位移变换节点。这样我们就可以将摄像机的位置置于坦克的后上访,以便进行观察。
int main( int argc, char **argv )
{
// 场景根节点和坦克模型节点指针。
osg::ref_ptr<osg::Group> rootNode;
osg::ref_ptr<osg::Group> ownTank;
osgGA::TrackballManipulator *Tman1 = new osgGA::TrackballManipulator();
osgGA::TrackballManipulator *Tman2 = new osgGA::TrackballManipulator();
// 建立场景和坦克。
if (!setupScene(rootNode, ownTank))
{
std::cout<< "problem setting up scene" << std::endl;
return -1;
}
// 声明一个位于坦克偏后上方的位移变换节点。将其添加到坦克节点。
osg::PositionAttitudeTransform * followerOffset =
new osg::PositionAttitudeTransform();
followerOffset->setPosition( osg::Vec3(0.0,-25.0,10) );
followerOffset->setAttitude(
osg::Quat( osg::DegreesToRadians(-15.0), osg::Vec3(1,0,0) ) );
ownTank.get()->addChild(followerOffset);
// 声明一个自定义的位移累加器类,以便放置相机。将其关联给上面的变换节点。
transformAccumulator* tankFollowerWorldCoords = new transformAccumulator();
tankFollowerWorldCoords->attachToGroup(followerOffset);
//