
osg::ClipNode
在 OpenSceneGraph(OSG)三维开发中,模型动态裁剪是可视化、剖切、内部结构展示的核心功能。
osg::ClipNode 正是 OSG 提供的专用裁剪节点,可以轻松实现模型剖切、区域可见性控制、动态切面等高级渲染效果。
本文将从继承关系、核心原理、使用方法、完整代码示例 四个维度,带你彻底掌握 osg::ClipNode。
什么是 osg::ClipNode
osg::ClipNode 是 OSG 中专门用于裁剪空间渲染 的节点类。
它通过定义裁剪平面(ClipPlane),对场景中的几何体进行"切割",只保留平面一侧的可见部分,常用于:
- 模型剖切视图
- 动态切面展示内部结构
- 区域可见性过滤
- 医学影像、机械模型、建筑模型剖面展示
一句话总结:
ClipNode = 场景的"空间切割器",通过平面控制模型哪些部分可见。
osg::ClipNode 完整继承关系
ClipNode 属于 OSG 场景树节点体系,继承链非常清晰:
osg::Object
↓
osg::Node
↓
osg::Group
↓
osg::ClipNode
各父类作用(必须理解)
-
osg::Object所有 OSG 对象的基类,提供引用计数、智能指针、克隆、命名能力。
-
osg::Node场景树节点基类,提供包围盒、更新回调、渲染状态基础能力。
-
osg::Group组节点基类,可以挂载子节点,是组合场景的基础。
-
osg::ClipNode继承组节点能力,自动管理裁剪平面与裁剪状态,将裁剪效果作用于所有子节点。
osg::ClipNode 核心原理
ClipNode 底层基于 OpenGL 裁剪平面(GL_CLIP_PLANE0~5) 实现:
- 创建 1~6 个裁剪平面
- 将平面参数传入 GPU
- 渲染时只保留平面正面的几何体
- 自动通过
StateSet管理裁剪开关与状态
它最大的优势:
- 不用修改模型数据
- 性能极高(GPU 硬件裁剪)
- 可动态移动/旋转平面
- 可嵌套、可组合、可继承
osg::ClipNode 常用 API
cpp
// 创建盒式裁剪(自动生成6个面,形成包围盒裁剪)
void createClipBox(const BoundingBox& bbox);
// 添加/移除裁剪平面
void addClipPlane(ClipPlane* p);
void removeClipPlane(unsigned int i);
// 获取/设置裁剪状态
StateSet* getStateSet();
// 启用/禁用自身拣选(避免裁剪平面被意外剔除)
void setCullingActive(false);
完整实战代码
以下代码基于标准 OSG 工程,实现:
- 动态旋转裁剪
- 线框渲染
- 实体+裁剪对比显示
cpp
#include <osg/Group>
#include <osg/StateSet>
#include <osg/PolygonMode>
#include <osg/MatrixTransform>
#include <osg/ClipNode>
#include <osg/ClipPlane>
#include <osg/BoundingSphere>
#include <osg/BoundingBox>
#include <osg/NodeCallback>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgUtil/Optimizer>
#include <iostream>
// 动态旋转回调:让裁剪平面持续旋转,实现动态剖切
class ClipRotateCallback : public osg::NodeCallback
{
public:
ClipRotateCallback(const osg::Vec3d& center, const osg::Vec3& axis, float speed)
: _center(center), _axis(axis), _speed(speed), _time(0.0), _lastTime(0.0) {}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);
if (mt && nv)
{
double delta = nv->getFrameStamp()->getReferenceTime() - _lastTime;
_time += delta;
_lastTime = nv->getFrameStamp()->getReferenceTime();
// 旋转矩阵
osg::Quat quat(osg::DegreesToRadians(_speed * _time), _axis);
mt->setMatrix(osg::Matrix::translate(_center) *
osg::Matrix::rotate(quat) *
osg::Matrix::translate(-_center));
}
traverse(node, nv);
}
private:
osg::Vec3d _center;
osg::Vec3 _axis;
float _speed;
double _time;
double _lastTime;
};
// 创建裁剪场景
osg::ref_ptr<osg::Node> createClipScene(osg::ref_ptr<osg::Node> model)
{
osg::ref_ptr<osg::Group> root = new osg::Group();
// ====================== 1. 线框模式 ======================
osg::ref_ptr<osg::StateSet> ssWire = new osg::StateSet();
osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode();
pm->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
ssWire->setAttributeAndModes(pm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
osg::ref_ptr<osg::Group> wireFrame = new osg::Group();
wireFrame->setStateSet(ssWire);
wireFrame->addChild(model);
root->addChild(wireFrame);
// ====================== 2. 动态裁剪节点 ======================
osg::ref_ptr<osg::MatrixTransform> animTrans = new osg::MatrixTransform();
animTrans->setUpdateCallback(new ClipRotateCallback(
model->getBound().center(),
osg::Vec3(0,0,1), // 旋转轴
45.0f // 旋转速度
));
// 创建 ClipNode
osg::ref_ptr<osg::ClipNode> clipNode = new osg::ClipNode();
osg::BoundingBox box;
box.expandBy(model->getBound());
clipNode->createClipBox(box); // 自动生成6个裁剪面
clipNode->setCullingActive(false); // 禁止剔除,保证裁剪生效
animTrans->addChild(clipNode);
clipNode->addChild(model);
root->addChild(animTrans);
// ====================== 3. 应用裁剪效果到实体模型 ======================
osg::ref_ptr<osg::Group> clippedModel = new osg::Group();
clippedModel->setStateSet(clipNode->getStateSet());
clippedModel->addChild(model);
root->addChild(clippedModel);
return root;
}
int main()
{
osgViewer::Viewer viewer;
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cessna.osg");
if (!model)
{
std::cout << "模型加载失败!" << std::endl;
return -1;
}
osg::ref_ptr<osg::Node> scene = createClipScene(model);
viewer.setSceneData(scene);
return viewer.run();
}

代码核心逻辑讲解
1. 动态裁剪回调
让裁剪平面自动旋转,实现模型动态剖切效果。
2. createClipBox
自动根据模型包围盒生成6个裁剪平面,形成盒式裁剪。
3. setCullingActive(false)
非常关键:
禁止裁剪节点被视锥体裁掉,保证裁剪平面永远生效。
4. 裁剪状态共享
clippedModel->setStateSet(clipNode->getStateSet())
让多个模型共用同一套裁剪状态,性能极高。
效果说明
运行后你将看到三部分模型:
- 左侧:线框模型
- 中间:动态旋转裁剪模型
- 右侧:应用了裁剪的实体模型
可以清晰看到模型内部结构,是机械、建筑、医疗可视化的标准方案。
总结
osg::ClipNode:OSG 官方标准空间裁剪节点。- 继承关系 :
Object → Node → Group → ClipNode。 - 核心能力:硬件加速裁剪、动态平面、多模型共享状态。
- 使用场景:模型剖切、切面展示、区域可见、内部结构查看。
