坐标
Vs = V * modelViewMatrix * projectionMatrix * windowMatrix
- V * modelViewMatrix * projectionMatrix为左手系,各分量在-1到1
unproject
- V0 = (Xs, Ys, 0) * invMVPW
- V1 = (Xs, Ys, 1) * invMVPW
相机
- osg::Camera 是group节点
-
功能
- 管理坐标
-
setViewMatrix
-
setViewMatrixAsLookAt
-
setProjectionMatrix
-
setProjectionMatrixAsFrustum
-
setProjectionMatrixAsOrtho
-
setProjectionMatrixAsOrtho2D
-
setProjectionMatrixAsPerspective
-
setViewport 参数为osg::Viewport
-
get*()
osg::Matrix viewMatrix = camera->getViewMatrix(); osg::Vec3 eye, center, up camera->getViewMatrixAsLookAt( eye, center, up );
-
- 封装opengl函数
- setClearMask 参数为GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
- setClearColor 参数为osg::Vec4
- setClearDepth
- setClearStencil
- setClearAccum
- get*()
- 显示上下文控制
- 缓冲区控制
- color buffer
- depth buffer
- …
- 管理坐标
-
多个相机共享显示上下文
-
设置相机顺序
camera1->setRenderOrder( osg::Camera::PRE_RENDER ); camera2->setRenderOrder( osg::Camera::PRE_RENDER, 5 ); camera3->setRenderOrder( osg::Camera::POST_RENDER );
-
- osgViewer::Viewer
- getCamera() 获取主相机,主相机是osgViewer自动生成并添加为子节点
示例
#include <osg/Camera>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("lz.osg");
osg::ref_ptr<osg::Node> hud_model = osgDB::readNodeFile("glider.osg");
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::POST_RENDER);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setViewMatrixAsLookAt(
osg::Vec3(0.0f, -5.0f, 5.0f), osg::Vec3(),
osg::Vec3(0.0f, 1.0f, 1.0f)
);
camera->addChild(hud_model.get());
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(model.get());
root->addChild( camera.get() );
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
return viewer.run();
}
视图类
-
osgViewer::Viewer
- 管理场景树
- setSceneData
- run()
- 指定主相机的控制器
- 设置显示上下文
- 帧循环
- setRunFrameScheme()参数为osgViewer::Viewer::ON_DEMAND/osgViewer::Viewer::CONTINUOUS
- setRunMaxFrameRate()
- done()
- Esc默认结束键
- setKeyEventSetsDone指定结束键
- setDone()
- getFrameStamp()获取帧信息
- 管理相机view matrix
-
setCameraManipulator(),参数为osgGA::CameraManipulator
viewer.setCameraManipulator( new osgGA::TrackballManipulator ); viewer.setCameraManipulator( NULL )
-

-
管理输入事件
- osgGA::GUIEventHandler
- view1->getCamera()->setAllowEventFocus( false );
-
显示
- 设置屏幕坐标
- setUpViewInWindow
- 设置屏幕
- setUpViewOnSingleScreen 参数为代表显示器的整数序号
- setUpViewFor3DSphericalDisplay 球面显示
- 设置屏幕坐标
- 管理场景树
-
osgViewer::CompositeViewer
- run()
- frame()
- done()
- addView()
- removeView()
- getView() 返回osgViewer::View,是osgViewer::Viewer的基类,无run()和frame(),不能用作单一视图
示例–osgViewer::Viewer
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgViewer/Viewer>
#include <iostream>
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("lz.osg");
osgViewer::Viewer viewer;
viewer.setSceneData(model.get());
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
while (!viewer.done())
{
viewer.frame();
std::cout << "Frame number: " <<
viewer.getFrameStamp()->getFrameNumber() << std::endl;
}
return 0;
}
示例–osgViewer::CompositeViewer
#include <osgDB/ReadFile>
#include <osgViewer/CompositeViewer>
osgViewer::View* createView(int x, int y, int w, int h,
osg::Node* scene)
{
osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
view->setSceneData(scene);
view->setUpViewInWindow(x, y, w, h);
return view.release();
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("cessna.osg");
osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::Node> model3 = osgDB::readNodeFile("glider.osg");
osgViewer::View* view1 = createView(50, 50, 320, 240, model1);
osgViewer::View* view2 = createView(370, 50, 320, 240, model2);
osgViewer::View* view3 = createView(185, 310, 320, 240, model3);
osgViewer::CompositeViewer viewer;
viewer.addView(view1);
viewer.addView(view2);
viewer.addView(view3);
return viewer.run();
}
注:通过多个相机的setViewport()也可在同一视图不同区域绘制,但是事件不独立
相机/视图等的默认全局设置
osg::DisplaySettings* ds = osg::DisplaySettings::instance();
- setDoubleBuffer() 开/关
- setDepthBuffer 开/关
- setMinimumNumAlphaBits 设置alpha buffer, a stencil buffer, and an accumulation buffer位数,默认为0
- setNumMultiSamples 设置多重采样,默认为0
- 设置stereo渲染
示例
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
int main(int argc, char** argv)
{
osg::DisplaySettings::instance()->setNumMultiSamples(4);
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cessna.osg");
osgViewer::Viewer viewer;
viewer.setSceneData(model.get());
return viewer.run();
}
立体视觉
-
setStereoMode()
- ANAGLYPHIC
- QUAD_BUFFER
- HORIZONTAL_SPLIT
- VERTICAL_SPLIT
- HORIZONTAL_INTERLACE
- VERTICAL_INTERLACE
- CHECKERBOARD
- LEFT_EYE
- RIGHT_EYE
-
setStereo
osg::DisplaySettings::instance()->setStereoMode( mode ); osg::DisplaySettings::instance()->setStereo( true ); osg::DisplaySettings::instance()->setStereoMode(osg::DisplaySettings::ANAGLYPHIC); osg::DisplaySettings::instance()->setEyeSeparation(0.05f); osg::DisplaySettings::instance()->setStereo(true);
示例
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
int main(int argc, char** argv)
{
osg::DisplaySettings::instance()->setStereoMode(osg::DisplaySettings::ANAGLYPHIC);
osg::DisplaySettings::instance()->setEyeSeparation(0.05f);
osg::DisplaySettings::instance()->setStereo(true);
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(
"cessna.osg");
osgViewer::Viewer viewer;
viewer.setSceneData(model.get());
return viewer.run();
}
渲染到纹理
- 三种方法
- 直接拷贝默认frame buffer,默认使用
- camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER );
- 内部使用glCopyTexSubImage拷贝到附加到相机的纹理
- camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER );
- pixel buffer 直接渲染到pixel buffer
- camera->setRenderTargetImplementation( osg::Camera::PIXEL_BUFFER );
- FBO 渲染到自定义FBO
- camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
- 直接拷贝默认frame buffer,默认使用
- 步骤
- 创建纹理
- osg::Texture
- setTextureSize()
- 渲染到纹理
-
osg::Camera::COLOR_BUFFER
-
osg::Camera::COLOR_BUFFER0-osg::Camera::COLOR_BUFFER15
-
osg::Camera::DEPTH_BUFFER
-
osg::Camera::STENCIL_BUFFER
camera->attach( osg::Camera::COLOR_BUFFER, texture.get() );
-
- 使用纹理
- 创建纹理
示例–渲染到纹理
#include <osg/Camera>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgViewer/Viewer>
class FindTextureVisitor : public osg::NodeVisitor
{
public:
FindTextureVisitor(osg::Texture* tex) : _texture(tex)
{
setTraversalMode(
osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
}
virtual void apply(osg::Node& node);
virtual void apply(osg::Geode& geode);
void replaceTexture(osg::StateSet* ss);
protected:
osg::ref_ptr<osg::Texture> _texture;
};
void FindTextureVisitor::apply(osg::Node& node)
{
replaceTexture(node.getStateSet());
traverse(node);
}
void FindTextureVisitor::apply(osg::Geode& geode)
{
replaceTexture(geode.getStateSet());
for (unsigned int i = 0; i<geode.getNumDrawables(); ++i)
{
replaceTexture(geode.getDrawable(i)->getStateSet());
}
traverse(geode);
}
void FindTextureVisitor::replaceTexture(osg::StateSet* ss)
{
if (ss)
{
osg::Texture* oldTexture = dynamic_cast<osg::Texture*>(
ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
);
if (oldTexture) ss->setTextureAttribute(
0, _texture.get());
}
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("lz.osg");
osg::ref_ptr<osg::Node> sub_model = osgDB::readNodeFile("glider.osg");
int tex_width = 1024, tex_height = 1024;
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_RGBA);
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
FindTextureVisitor ftv(texture.get());
if (model.valid()) model->accept(ftv);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setViewport(0, 0, tex_width, tex_height);
camera->setClearColor(osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
camera->attach(osg::Camera::COLOR_BUFFER, texture.get());
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->addChild(sub_model.get());
osgViewer::Viewer viewer;
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(model.get());
root->addChild(camera.get());
viewer.setSceneData(root.get());
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
float delta = 0.1f, bias = 0.0f;
osg::Vec3 eye(0.0f, -5.0f, 5.0f);
while (!viewer.done())
{
if (bias<-1.0f) delta = 0.1f;
else if (bias>1.0f) delta = -0.1f;
bias += delta;
camera->setViewMatrixAsLookAt(eye, osg::Vec3(), osg::Vec3(bias, 1.0f, 1.0f));
viewer.frame();
}
return 0;
}
示例–渲染并保存图片
#include <osg/Camera>
#include <osgDB/WriteFile>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgViewer/Viewer>
class FindTextureVisitor : public osg::NodeVisitor
{
public:
FindTextureVisitor(osg::Texture* tex) : _texture(tex)
{
setTraversalMode(
osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
}
virtual void apply(osg::Node& node);
virtual void apply(osg::Geode& geode);
void replaceTexture(osg::StateSet* ss);
protected:
osg::ref_ptr<osg::Texture> _texture;
};
void FindTextureVisitor::apply(osg::Node& node)
{
replaceTexture(node.getStateSet());
traverse(node);
}
void FindTextureVisitor::apply(osg::Geode& geode)
{
replaceTexture(geode.getStateSet());
for (unsigned int i = 0; i<geode.getNumDrawables(); ++i)
{
replaceTexture(geode.getDrawable(i)->getStateSet());
}
traverse(geode);
}
void FindTextureVisitor::replaceTexture(osg::StateSet* ss)
{
if (ss)
{
osg::Texture* oldTexture = dynamic_cast<osg::Texture*>(
ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
);
if (oldTexture) ss->setTextureAttribute(
0, _texture.get());
}
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("lz.osg");
osg::ref_ptr<osg::Node> sub_model = osgDB::readNodeFile("glider.osg");
int tex_width = 1024, tex_height = 1024;
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_RGBA);
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
FindTextureVisitor ftv(texture.get());
if (model.valid()) model->accept(ftv);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setViewport(0, 0, tex_width, tex_height);
camera->setClearColor(osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
camera->attach(osg::Camera::COLOR_BUFFER, texture.get());
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->addChild(sub_model.get());
osg::ref_ptr<osg::Image> image = new osg::Image;
osg::ref_ptr<osg::Camera> camera2 = new osg::Camera;
camera2->setClearColor(osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
camera2->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera2->setRenderOrder(osg::Camera::POST_RENDER);
camera2->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER);
camera2->attach(osg::Camera::COLOR_BUFFER, image.get());
camera2->addChild(model.get());
osgViewer::Viewer viewer;
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(camera2.get());
root->addChild(camera.get());
viewer.setSceneData(root.get());
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
float delta = 0.1f, bias = 0.0f;
osg::Vec3 eye(0.0f, -5.0f, 5.0f);
while (!viewer.done())
{
if (bias<-1.0f) delta = 0.1f;
else if (bias>1.0f) delta = -0.1f;
bias += delta;
camera->setViewMatrixAsLookAt(eye, osg::Vec3(), osg::Vec3(bias, 1.0f, 1.0f));
viewer.frame();
if(viewer.getFrameStamp()->getFrameNumber()%120==0)
osgDB::writeImageFile(*image, "saved_image.bmp");
}
return 0;
}
这篇博客详细介绍了OpenGL中的osg库如何管理和控制相机,包括坐标系统、相机的视图矩阵和投影矩阵设置,以及osgViewer::Viewer和osgViewer::CompositeViewer的使用。还涉及了相机的默认全局设置,如立体视觉的实现,以及如何渲染到纹理并保存图片。内容涵盖从基本的相机操作到复杂的视图管理,是理解osg中相机和视图控制的重要参考资料。
7119

被折叠的 条评论
为什么被折叠?



