已知相机世界坐标系(x,y,z),相机姿态(pictch,roll,yaw),如何设置cmamera?
如题,急问. 相机位置是matrix = rotationMatrix * translateMatrix,这两个矩阵显然都可以通过您的已知参数求出;而相机的观察矩阵则是其位置姿态矩阵的逆矩阵,使用setViewMatrix( inverse(matrix) )就可以设置了 观察矩阵是位置姿态的逆啊,怎么理解呢? 想象一下就可以了:观察者在世界中的运动,可以理解为世界在观察者眼中的逆运动 奥~~就是的啊~~呵呵,相对运动啊 4# array
请教下,求逆的矩阵为什么在乘以旋转矩阵后又求逆,然后再设置?前一个求逆可以理解,后一个不是很理解?
//对于摄像机来说,观察矩阵 = 位置姿态矩阵的逆矩阵。
osg::Matrixd i = myCameraMatrix.inverse(myCameraMatrix);
//设置观察矩阵
Tman->setByInverseMatrix(
osg::Matrix(i.ptr())
* osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ) ); Tman是您的漫游器对象?如果这样的话,setByInverseMatrix表示按照观察矩阵(也就是漫游器位置矩阵的逆矩阵)来进行设置 7# array
那漫游器与摄像机具体什么关系呢? 前面的求逆是求摄像机的观察矩阵?后面的求逆怎么又是漫游器的观察矩阵? 有点混淆。 漫游器设置的是相机在世界坐标中的位置姿态矩阵;而相机的观察矩阵表达的是世界在观察坐标系下的位置姿态。这两个矩阵互为逆矩阵,即,相机在世界中的姿态,就是世界在相机中的姿态的逆过程。 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来设置呢?前面一个求逆不是已经得到观察矩阵了? 我想我已经回答过这个问题了,如果您还是不理解,请设法自行回答几个问题,然后想必就会明白这段代码的意思:
1、myCameraMatrix是什么?是相机在世界坐标系下的位置矩阵?还是观察矩阵?
2、setByInverseMatrix是什么意思?是“直接设置相机在世界中的位置矩阵”?还是“根据相机的观察矩阵设置相机在世界中的位置”? 11# array
哦,我似乎有点理解了。myCameraMatrix 是相机在世界坐标系中的位置姿态矩阵,然后求逆得到相机在世界坐标系中的观察矩阵,setByInverseMatrix 是根据观察矩阵来设置相机在世界坐标系中的位置,那如果是setByMatrix则应该是直接设置相机在世界坐标系中的位置. 我的回答正确吗?谢谢王锐的指导!
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下面没有这个函数了? 视景器设置与漫游器的设置似乎又有区别? viewer没有这个函数了,视景器就是视景器,漫游器就是漫游器,本身就不应该由前者来设置观察矩阵。海军教程本身已经很旧了,不适合再深入研究 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,但是通过摄像机而不是漫游器来直接设置观察矩阵,效果好像不一样?问下,通过摄像机这样设置观察矩阵可以吗? 我看大部分都是用漫游器来设置的。谢谢! 11# array
我还想问下,一个视景器,设置了一个漫游器,下面添加了两个摄像机,对应相同的场景数据,不同位置的viewport设置,那么通过其中一个摄像机设置跟随结点的观察矩阵,能显示出两个不同的视角吗? 那多视景器的设置是不是为了观察不同的场景数据来设置的? 还有就是viewer和view究竟在osg中有什么区别?谢谢。 您的《最长的一帧》感觉对于我们这些初学者看起来还是挺吃力的。如果可以写的再通俗些可能会更好。 如果想直接设置相机观察矩阵,那么需要取消漫游器的设置,即setCameraManipulator(NULL)并且不要执行viewer.run()
一个视景器,设置了一个漫游器,下面添加了两个摄像机,对应相同的场景数据,不同位置的viewport设置,那么通过其中一个摄像机设置跟随结点的观察矩阵,能显示出两个不同的视角吗我完全不明白您的意思
还有就是viewer和view究竟在osg中有什么区别Viewer类派生自View类。不同的是Viewer本身还可以管理用户事件和渲染线程;而View则是作为CompositeViewer的一个视图存在的,后者负责各个视图的事件传递和渲染线程管理
您的《最长的一帧》感觉对于我们这些初学者看起来还是挺吃力的初学者请不要阅读《最长的一帧》,它是专门为OSG内部机理的探求者准备的。《快速入门指导》更适合您 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();
}
那这样写是不是不起作用的? 望指教。 “不要使用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了 19# array
哦,看来我又有点问题了,我看很多程序经常将“viewer.run()” 与
"while( !viewer.done() ){ viewer.frame();}" 替换着用,所以我就觉得我用了后者,就相当与用了前者,那他们之间有什么区别呢? 这个时候花一分钟时间来阅读一下viewer.run()的简短源代码,这恐怕要方便和快捷许多 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 却可以看到两个窗口不同的场景。 是不是因为使用的是同一个漫游器,所以摄像机的设置不起作用了?
tankFollowerCamera->setViewMatrix(tankFollowerWorldCoords->getMatrix()
*osg::Matrix::rotate( -3.1415926/2.0, 1, 0, 0 ));
既然您已经取消了漫游器,那么这里相机的设置必然起作用了,看不到的原因恐怕是您没有正确计算观察的参数 哥们,能否把包含头文件什么的贴出来啊,借用一下,感谢 那么已经有了投影矩阵和视图矩阵(opengGL中得到经过转置),该如何设置显示固定视角的场景呢? array 发表于 2009-12-21 08:33
相机位置是matrix = rotationMatrix * translateMatrix,这两个矩阵显然都可以通过您的已知参数求出;
而 ...
请问怎么跟着已知条件求出这个矩阵matrix呢?
页:
[1]