关键是HUD技术和重写advance()
HUD参考这篇文章:OSG的HUD抬头文字显示
众所周知,osgViewer每一帧渲染都会调用frame函数,因此要实现动态修改,理论上重写frame里的几个函数哪一个都可以的。
这里重写advance函数,每次删除原来的文字节点,加载新的文字节点,效果如下:
代码如下:
#include <osg/Geode>
#include <osgText/Text>
#include <osg/Depth>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
osg::Node* addHUD(const wchar_t* s)
{
osgText::Text* text = new osgText::Text;
std::string caiyun("fonts /simhei.ttf");//此处设置的是汉字字体
text->setFont(caiyun);
text->setPosition(osg::Vec3(0.0f, 10.0f, 0.0f));//设置文字位置
text->setColor(osg::Vec4(1, 1, 0, 1));
text->setText(s);//设置显示的文字
//几何体节点
osg::Geode* geode = new osg::Geode();
geode->addDrawable(text);//将文字Text作这drawable加入到Geode节点中
//设置状态
osg::StateSet* stateset = geode->getOrCreateStateSet();
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);//关闭灯光
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);//关闭深度测试
//打开GL_BLEND混合模式(以保证Alpha纹理正确)
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
osg::Camera* camera = new osg::Camera;
camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 600, 0, 600));//正交投影
//设置绝对参考坐标系,确保视图矩阵不会被上级节点的变换矩阵影响
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
//视图矩阵为默认的
camera->setViewMatrix(osg::Matrix::identity());
//设置背景为透明,否则的话可以设置ClearColor
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setAllowEventFocus(false);//不响应事件,始终得不到焦点
camera->addChild(geode);//将要显示的Geode节点加入到相机
return camera;
};
class TimeViewer :public osgViewer::Viewer {
public:
TimeViewer() {};
~TimeViewer() {};
virtual void advance(double simulationTime = USE_REFERENCE_TIME);
};
void TimeViewer::advance(double simulationTime) {
Viewer::advance();
osg::ref_ptr<osg::Group> g = getSceneData()->asGroup();
g->removeChild(g->getNumChildren() - 1);
//显示程序运行时间
wchar_t buffer[200];
swprintf(buffer, L"时间:%.2f s \n", osg::Timer::instance()->time_s());
g->addChild(addHUD(buffer));
}
int main() {
osg::ref_ptr<osgViewer::Viewer> vi = new TimeViewer;
osg::ref_ptr<osg::Group> g = new osg::Group;
g->addChild(osgDB::readNodeFile("cow.osg"));
g->addChild(addHUD(L"111"));//just add a child
vi->setSceneData(g.get());
vi->setUpViewInWindow(600, 100, 800, 600);
return vi->run();
}