osg.PushPopValue
类是OpenSceneGraph中的一个辅助类,被用于保存OpenGL状态的堆栈。
当调用OpenGL函数时,OpenGL的状态会被改变,包括但不限于变换矩阵、材料属性、光照属性等等。因此,当多个场景共用同一OpenGL上下文时,为了避免状态冲突,通常需要将这些状态保存在堆栈中,并在每次场景绘制时恢复原状态。
osg.PushPopValue
类提供了一个方便的方式来将OpenGL状态保存在堆栈中,并在需要时回复原状态。
PushPopValue();
PushPopValue(const T& value);
PushPopValue(const PushPopValue<T>& ppv, const T& value);
参数
value
:类型为T
,表示要保存的值。void push(const T& value);
T& get();
const T& get() const;
void pop();
std::size_t size() const;
将当前的值压入堆栈,并用指定的值替换当前值。
参数
value
:类型为T
,表示要保存在堆栈中的值。返回当前保存的值,并将其标记为已使用。
从堆栈中弹出一个值,并将其作为当前的值。
返回堆栈中的元素数量。
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include <osg/NodeVisitor>
#include <osg/Node>
#include <osg/PolygonMode>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
class SetPolygonModeVisitor : public osg::NodeVisitor
{
public:
SetPolygonModeVisitor(osg::PolygonMode::Face face, osg::PolygonMode::Mode mode)
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
m_polygonMode(face)
{
m_polygonMode.setMode(mode);
}
virtual void apply(osg::Geometry& geom)
{
osg::StateSet* ss = geom.getOrCreateStateSet();
osg::PolygonMode* polygonMode = new osg::PolygonMode;
polygonMode->setMode(m_polygonMode);
ss->setAttributeAndModes(polygonMode, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
}
private:
osg::PolygonMode::Face m_polygonMode;
};
int main()
{
// 读取模型
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cow.osg");
// 创建根节点
osg::ref_ptr<osg::Group> root = new osg::Group;
// 创建保存状态的堆栈
osg::PushPopValue<osg::PolygonMode::Face> saveFace;
// 创建三个子节点
osg::ref_ptr<osg::MatrixTransform> mt1 = new osg::MatrixTransform;
mt1->setMatrix(osg::Matrix::translate(-3, 0, 0));
mt1->addChild(model);
osg::ref_ptr<osg::MatrixTransform> mt2 = new osg::MatrixTransform;
mt2->setMatrix(osg::Matrix::translate(0, 0, 0));
mt2->addChild(model);
osg::ref_ptr<osg::MatrixTransform> mt3 = new osg::MatrixTransform;
mt3->setMatrix(osg::Matrix::translate(3, 0, 0));
mt3->addChild(model);
// 添加子节点到根节点
root->addChild(mt1);
root->addChild(mt2);
root->addChild(mt3);
// 设置绘制模式为填充模式
osg::PolygonMode::Face face = osg::PolygonMode::FRONT_AND_BACK;
osg::ref_ptr<SetPolygonModeVisitor> setPolygonModeVisitor = new SetPolygonModeVisitor(face, osg::PolygonMode::FILL);
root->accept(*setPolygonModeVisitor);
// 开启不同的Face culling
face = osg::PolygonMode::FRONT;
setPolygonModeVisitor = new SetPolygonModeVisitor(face, osg::PolygonMode::LINE);
root->accept(*setPolygonModeVisitor);
face = osg::PolygonMode::BACK;
setPolygonModeVisitor = new SetPolygonModeVisitor(face, osg::PolygonMode::POINT);
root->accept(*setPolygonModeVisitor);
// 还原绘制模式
root->accept(*setPolygonModeVisitor);
// 在场景图中添加保存Face culling的堆栈
{
osg::PushPopValue<osg::PolygonMode::Face> ppv;
ppv.push(osg::PolygonMode::FRONT);
// 此时堆栈中的值为FRONT
ppv.push(osg::PolygonMode::BACK);
// 此时堆栈中的值为BACK, FRONT
ppv.push(osg::PolygonMode::FRONT_AND_BACK);
// 此时堆栈中的值为FRONT_AND_BACK, BACK, FRONT
// 保存堆栈
saveFace.push(osg::PolygonMode::BACK);
saveFace.push(ppv.get());
// 此时堆栈中的值为ppv, BACK
// 设置 Face culling
osg::ref_ptr<SetPolygonModeVisitor> setPolygonModeVisitor = new SetPolygonModeVisitor(ppv.get(), osg::PolygonMode::LINE);
root->accept(*setPolygonModeVisitor);
// ... 更新场景...
// 还原 Face culling
root->accept(*setPolygonModeVisitor);
// 还原堆栈中的值
ppv = saveFace.get();
saveFace.pop();
// ... 更新场景...
}
// 创建 viewer
osgViewer::Viewer viewer;
viewer.setSceneData(root);
return viewer.run();
}