查看: 6452|回复: 25

已知相机世界坐标系(x,y,z),相机姿态(pictch,roll,yaw),如何设置cmamera?

[复制链接]

该用户从未签到

发表于 2009-12-20 21:27:52 | 显示全部楼层 |阅读模式
如题,急问.

该用户从未签到

发表于 2009-12-21 08:33:16 | 显示全部楼层
相机位置是matrix = rotationMatrix * translateMatrix,这两个矩阵显然都可以通过您的已知参数求出;
而相机的观察矩阵则是其位置姿态矩阵的逆矩阵,使用setViewMatrix( inverse(matrix) )就可以设置了

该用户从未签到

发表于 2009-12-21 10:11:18 | 显示全部楼层
观察矩阵是位置姿态的逆啊,怎么理解呢?

该用户从未签到

发表于 2009-12-21 10:15:34 | 显示全部楼层
想象一下就可以了:观察者在世界中的运动,可以理解为世界在观察者眼中的逆运动

该用户从未签到

发表于 2009-12-21 13:26:20 | 显示全部楼层
奥~~就是的啊~~呵呵,相对运动啊

该用户从未签到

发表于 2010-4-1 18:25:19 | 显示全部楼层
4# array

请教下,求逆的矩阵为什么在乘以旋转矩阵后又求逆,然后再设置?前一个求逆可以理解,后一个不是很理解?

//对于摄像机来说,观察矩阵 = 位置姿态矩阵的逆矩阵。
         osg::Matrixd i = myCameraMatrix.inverse(myCameraMatrix);
         
   //设置观察矩阵
   Tman->setByInverseMatrix(
            osg::Matrix(i.ptr())
            * osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ) );

该用户从未签到

发表于 2010-4-1 18:58:15 | 显示全部楼层
Tman是您的漫游器对象?如果这样的话,setByInverseMatrix表示按照观察矩阵(也就是漫游器位置矩阵的逆矩阵)来进行设置

该用户从未签到

发表于 2010-4-7 09:29:59 | 显示全部楼层
7# array

那漫游器与摄像机具体什么关系呢? 前面的求逆是求摄像机的观察矩阵?后面的求逆怎么又是漫游器的观察矩阵? 有点混淆。

该用户从未签到

发表于 2010-4-7 10:54:43 | 显示全部楼层
漫游器设置的是相机在世界坐标中的位置姿态矩阵;而相机的观察矩阵表达的是世界在观察坐标系下的位置姿态。这两个矩阵互为逆矩阵,即,相机在世界中的姿态,就是世界在相机中的姿态的逆过程。

该用户从未签到

发表于 2010-4-7 11:09:19 | 显示全部楼层
9# array

osgGA::TrackballManipulator *Tman = new osgGA::TrackballManipulator();

osg::Matrixd myCameraMatrix;
   osg::Matrixd cameraRotation;
   osg::Matrixd cameraTrans;
   cameraRotation.makeRotate(
      osg:egreesToRadians(-20.0), osg::Vec3(0,1,0), // roll
      osg::DegreesToRadians(-15.0), osg::Vec3(1,0,0) , // pitch
      osg::DegreesToRadians( 10.0), osg::Vec3(0,0,1) ); // heading

cameraTrans.makeTranslate( 10,-50,15 );
   myCameraMatrix = cameraRotation * cameraTrans;

osg::Matrixd i = myCameraMatrix.inverse(myCameraMatrix);
         
   Tman->setByInverseMatrix(
            osg::Matrix(i.ptr())
            * osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ) );

我不清楚的是为什么这里要用两个inverse来设置呢?  前面一个求逆不是已经得到观察矩阵了?

该用户从未签到

发表于 2010-4-7 11:21:03 | 显示全部楼层
我想我已经回答过这个问题了,如果您还是不理解,请设法自行回答几个问题,然后想必就会明白这段代码的意思:
1、myCameraMatrix是什么?是相机在世界坐标系下的位置矩阵?还是观察矩阵?
2、setByInverseMatrix是什么意思?是“直接设置相机在世界中的位置矩阵”?还是“根据相机的观察矩阵设置相机在世界中的位置”?

该用户从未签到

发表于 2010-4-7 12:02:44 | 显示全部楼层
11# array

哦,我似乎有点理解了。myCameraMatrix 是相机在世界坐标系中的位置姿态矩阵,然后求逆得到相机在世界坐标系中的观察矩阵,setByInverseMatrix 是根据观察矩阵来设置相机在世界坐标系中的位置,那如果是setByMatrix则应该是直接设置相机在世界坐标系中的位置. 我的回答正确吗?  谢谢王锐的指导!

该用户从未签到

发表于 2010-4-7 12:20:55 | 显示全部楼层

11# array

但是海军教程中的代码如下:


osg::Matrixd i = myCameraMatrix.inverse(myCameraMatrix);

viewer.setViewByMatrix( (


Producer::Matrix(i.ptr() ))


* Producer::Matrix::rotate( -M_PI/2.0, 1, 0, 0 ) );


是不是现在不能通过视景器viewer来set了?发现现在viewer下面没有这个函数了? 视景器设置与漫游器的设置似乎又有区别?

该用户从未签到

发表于 2010-4-7 12:26:08 | 显示全部楼层
viewer没有这个函数了,视景器就是视景器,漫游器就是漫游器,本身就不应该由前者来设置观察矩阵。海军教程本身已经很旧了,不适合再深入研究

该用户从未签到

发表于 2010-4-9 13:37:41 | 显示全部楼层
14# array


while( !viewer.done() )
{
  tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix()
                         *osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
  //Tman2->setByInverseMatrix(tankFollowerWorldCoords->getMatrix()
   //*osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
  viewer.frame();
}
tman2漫游器对应的是tankFollowerCamera,但是通过摄像机而不是漫游器来直接设置观察矩阵,效果好像不一样?问下,通过摄像机这样设置观察矩阵可以吗? 我看大部分都是用漫游器来设置的。谢谢!

该用户从未签到

发表于 2010-4-9 14:06:07 | 显示全部楼层
11# array


我还想问下,一个视景器,设置了一个漫游器,下面添加了两个摄像机,对应相同的场景数据,不同位置的viewport设置,那么通过其中一个摄像机设置跟随结点的观察矩阵,能显示出两个不同的视角吗? 那多视景器的设置是不是为了观察不同的场景数据来设置的? 还有就是viewer和view究竟在osg中有什么区别?谢谢。 您的《最长的一帧》感觉对于我们这些初学者看起来还是挺吃力的。如果可以写的再通俗些可能会更好。

该用户从未签到

发表于 2010-4-9 16:10:23 | 显示全部楼层
如果想直接设置相机观察矩阵,那么需要取消漫游器的设置,即setCameraManipulator(NULL)并且不要执行viewer.run()

一个视景器,设置了一个漫游器,下面添加了两个摄像机,对应相同的场景数据,不同位置的viewport设置,那么通过其中一个摄像机设置跟随结点的观察矩阵,能显示出两个不同的视角吗
我完全不明白您的意思

还有就是viewer和view究竟在osg中有什么区别
Viewer类派生自View类。不同的是Viewer本身还可以管理用户事件和渲染线程;而View则是作为CompositeViewer的一个视图存在的,后者负责各个视图的事件传递和渲染线程管理

您的《最长的一帧》感觉对于我们这些初学者看起来还是挺吃力的
初学者请不要阅读《最长的一帧》,它是专门为OSG内部机理的探求者准备的。《快速入门指导》更适合您

该用户从未签到

发表于 2010-4-10 10:49:18 | 显示全部楼层
17# array


你说不要使用viewer.run() , 那我如果要每一帧都需要camera设置viewMatrix应该在哪里设置呢? 也就是结点在动,摄像机要跟着结点动。

   while( !viewer.done() )
        {
         tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix()
                                *osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));

         viewer.frame();
        }
那这样写是不是不起作用的? 望指教。

该用户从未签到

发表于 2010-4-12 08:25:37 | 显示全部楼层
“不要使用viewer.run()”,难道您的程序片断不是这样做的?

  1. viewer.setCameraManipulator(NULL)
  2. while( !viewer.done() )
  3. {
  4.     tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix() *osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
  5.     viewer.frame();
  6. }
复制代码
这样就可以按您的特定要求来设置viewMatrix了

该用户从未签到

发表于 2010-4-12 22:10:54 | 显示全部楼层
19# array


哦,看来我又有点问题了,我看很多程序经常将“viewer.run()” 与

  "while( !viewer.done() )  { viewer.frame();}" 替换着用,所以我就觉得我用了后者,就相当与用了前者,那他们之间有什么区别呢?

该用户从未签到

发表于 2010-4-12 23:37:03 | 显示全部楼层
这个时候花一分钟时间来阅读一下viewer.run()的简短源代码,这恐怕要方便和快捷许多

该用户从未签到

发表于 2010-4-14 14:02:15 | 显示全部楼层
21# array

int main( int argc, char **argv )
{
//pointers to the root node and the tank model node
osg::ref_ptr<osg::Group> rootNode;
osg::ref_ptr<osg::Group> ownTank;
///osg::ref_ptr<osg::Node> scene;
// build scene with terrain and two tanks
if (!setupScene(rootNode, ownTank))
{
    std::cout<< "problem setting up scene" << std::endl;
    return -1;
}
// Declare a transform for a position above and behind the tank
// aimed down slightly. Add this transform to the tank node.
osg:ositionAttitudeTransform * followerOffset =
    new osg::PositionAttitudeTransform();
followerOffset->setPosition( osg::Vec3(0.0,-25.0,10) );
followerOffset->setAttitude(
    osg:uat( osg:egreesToRadians(-15.0), osg::Vec3(1,0,0) ) );
ownTank.get()->addChild(followerOffset);

// Declare a transform accumulator to be used to position a
// camera. Attach transform accumulator to the follower transform.
transformAccumulator* tankFollowerWorldCoords =
    new transformAccumulator();
tankFollowerWorldCoords->attachToGroup(followerOffset);
  //构建视口类,以及与其相关的图形设备类。
osgViewer::Viewer viewer;
osg::GraphicsContext::WindowingSystemInterface* wsi =
  osg::GraphicsContext::getWindowingSystemInterface();
if (!wsi)
{
  osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
  return 1;
}
unsigned int width, height;
wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 100;
traits->y = 100;
traits->width = width;
traits->height = height;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if (gc.valid())
{
  osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<std::endl;
  gc->setClearColor(osg::Vec4f(0.2f,0.2f,0.6f,1.0f));
  gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
else
{
  osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
}
    //设置mainCamera的视口参数
osg::Camera* mainCamera = new osg::Camera;
mainCamera->setGraphicsContext(gc.get());
mainCamera->setViewport(0, 0, traits->width/2, traits->height);
mainCamera->addChild( rootNode.get() );
//设置tankFollowCamera的视口参数
osg::Camera* tankFollowerCamera = new osg::Camera;
tankFollowerCamera->setGraphicsContext(gc.get());
tankFollowerCamera->setViewport(traits->width/2, 0, traits->width, traits->height);
tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix()*osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
tankFollowerCamera->addChild( rootNode.get() );
viewer.addSlave(mainCamera, true);
viewer.addSlave(tankFollowerCamera, true);
viewer.setSceneData( rootNode.get() );
//osgGA::TrackballManipulator *Tman = new osgGA::TrackballManipulator();
viewer.setCameraManipulator(NULL);

viewer.realize();

while( !viewer.done() )
{
  //是不是因为使用的是同一个漫游器,所以摄像机的设置不起作用了?
  tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix()
                         *osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
  viewer.frame();
}

}

但是我不知道为什么这样设置后却什么也看不到?而我如果用compesiteView 通过加入两个view 却可以看到两个窗口不同的场景。

该用户从未签到

发表于 2010-4-14 17:08:32 | 显示全部楼层
是不是因为使用的是同一个漫游器,所以摄像机的设置不起作用了?
  tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix()
                         *osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
既然您已经取消了漫游器,那么这里相机的设置必然起作用了,看不到的原因恐怕是您没有正确计算观察的参数

该用户从未签到

发表于 2010-12-30 09:59:48 | 显示全部楼层
哥们,能否把包含头文件什么的贴出来啊,借用一下,感谢

该用户从未签到

发表于 2016-2-24 22:08:48 | 显示全部楼层
那么已经有了投影矩阵和视图矩阵(opengGL中得到经过转置),该如何设置显示固定视角的场景呢?
  • TA的每日心情
    难过
    2020-5-2 10:51
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2020-5-15 09:00:34 | 显示全部楼层
    array 发表于 2009-12-21 08:33
    相机位置是matrix = rotationMatrix * translateMatrix,这两个矩阵显然都可以通过您的已知参数求出;
    而 ...

    请问怎么跟着已知条件求出这个矩阵matrix呢?
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    OSG中国官方论坛-有您OSG在中国才更好

    网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

    联系我们

    • 工作时间:09:00--18:00
    • 反馈邮箱:1315785073@qq.com
    快速回复 返回顶部 返回列表