没出息的汉子 发表于 2009-12-20 21:27:52

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

如题,急问.

array 发表于 2009-12-21 08:33:16

相机位置是matrix = rotationMatrix * translateMatrix,这两个矩阵显然都可以通过您的已知参数求出;
而相机的观察矩阵则是其位置姿态矩阵的逆矩阵,使用setViewMatrix( inverse(matrix) )就可以设置了

tianxiao888 发表于 2009-12-21 10:11:18

观察矩阵是位置姿态的逆啊,怎么理解呢?

array 发表于 2009-12-21 10:15:34

想象一下就可以了:观察者在世界中的运动,可以理解为世界在观察者眼中的逆运动

tianxiao888 发表于 2009-12-21 13:26:20

奥~~就是的啊~~呵呵,相对运动啊

hy05190134 发表于 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 ) );

array 发表于 2010-4-1 18:58:15

Tman是您的漫游器对象?如果这样的话,setByInverseMatrix表示按照观察矩阵(也就是漫游器位置矩阵的逆矩阵)来进行设置

hy05190134 发表于 2010-4-7 09:29:59

7# array

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

array 发表于 2010-4-7 10:54:43

漫游器设置的是相机在世界坐标中的位置姿态矩阵;而相机的观察矩阵表达的是世界在观察坐标系下的位置姿态。这两个矩阵互为逆矩阵,即,相机在世界中的姿态,就是世界在相机中的姿态的逆过程。

hy05190134 发表于 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::DegreesToRadians(-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来设置呢?前面一个求逆不是已经得到观察矩阵了?

array 发表于 2010-4-7 11:21:03

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

hy05190134 发表于 2010-4-7 12:02:44

11# array

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

hy05190134 发表于 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下面没有这个函数了? 视景器设置与漫游器的设置似乎又有区别?

array 发表于 2010-4-7 12:26:08

viewer没有这个函数了,视景器就是视景器,漫游器就是漫游器,本身就不应该由前者来设置观察矩阵。海军教程本身已经很旧了,不适合再深入研究

hy05190134 发表于 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,但是通过摄像机而不是漫游器来直接设置观察矩阵,效果好像不一样?问下,通过摄像机这样设置观察矩阵可以吗? 我看大部分都是用漫游器来设置的。谢谢!

hy05190134 发表于 2010-4-9 14:06:07

11# array


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

array 发表于 2010-4-9 16:10:23

如果想直接设置相机观察矩阵,那么需要取消漫游器的设置,即setCameraManipulator(NULL)并且不要执行viewer.run()

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

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

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

hy05190134 发表于 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();
        }
那这样写是不是不起作用的? 望指教。

array 发表于 2010-4-12 08:25:37

“不要使用viewer.run()”,难道您的程序片断不是这样做的?
viewer.setCameraManipulator(NULL)
while( !viewer.done() )
{
    tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix() *osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
    viewer.frame();
}这样就可以按您的特定要求来设置viewMatrix了

hy05190134 发表于 2010-4-12 22:10:54

19# array


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

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

array 发表于 2010-4-12 23:37:03

这个时候花一分钟时间来阅读一下viewer.run()的简短源代码,这恐怕要方便和快捷许多

hy05190134 发表于 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::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);

// 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 却可以看到两个窗口不同的场景。

array 发表于 2010-4-14 17:08:32

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

zhoujiajun2010 发表于 2010-12-30 09:59:48

哥们,能否把包含头文件什么的贴出来啊,借用一下,感谢

stonels 发表于 2016-2-24 22:08:48

那么已经有了投影矩阵和视图矩阵(opengGL中得到经过转置),该如何设置显示固定视角的场景呢?

xiaoxiaobx 发表于 2020-5-15 09:00:34

array 发表于 2009-12-21 08:33
相机位置是matrix = rotationMatrix * translateMatrix,这两个矩阵显然都可以通过您的已知参数求出;
而 ...

请问怎么跟着已知条件求出这个矩阵matrix呢?
页: [1]
查看完整版本: 已知相机世界坐标系(x,y,z),相机姿态(pictch,roll,yaw),如何设置cmamera?