当前位置: 首页 > news >正文

【OSG学习笔记】Day 12: 回调机制——动态更新场景

在这里插入图片描述

UpdateCallback

在OpenSceneGraph(OSG)里,UpdateCallback是用来动态更新场景的关键机制。

借助UpdateCallback,你能够实现节点的动画效果,像旋转、位移等。

NodeCallback

osg::NodeCallback 是一个更通用的回调类,它能在节点遍历的任何阶段被调用。

osg::UpdateCallback 实际上是 osg::NodeCallback 的一个子类,专门用于更新遍历。

NodeCallback 可用于在不同的遍历阶段执行自定义操作,例如在裁剪遍历、绘制遍历等阶段。。

实现旋转动画的RotateCallback

我们借用上一届可得钢铁侠模型来实现效果。

直接上代码,代码里注释很明白:

#include <osg/NodeCallback>
#include <osg/MatrixTransform>
#include <osgViewer/Viewer>// 自定义旋转更新回调类
class RotateCallback : public osg::NodeCallback
{
public:RotateCallback(float speed) : _speed(speed), _angle(0.0f) {}virtual void operator()(osg::Node* node, osg::NodeVisitor* nv){// 转换为MatrixTransform节点osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);if (transform){// 计算时间间隔double deltaTime = nv->getFrameStamp()->getSimulationTime() - _lastTime;_lastTime = nv->getFrameStamp()->getSimulationTime();// 更新旋转角度_angle += _speed * deltaTime;// 设置旋转矩阵osg::Matrix matrix;matrix.makeRotate(_angle, osg::Vec3(0.0f, 0.0f, 1.0f));transform->setMatrix(matrix);}// 继续遍历子节点traverse(node, nv);}private:float _speed;  // 旋转速度float _angle;  // 旋转角度double _lastTime = 0.0;  // 上一帧的时间
};int main()
{// 创建Viewer对象osgViewer::Viewer viewer;// 创建一个MatrixTransform节点osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;// 创建一个简单的几何体,例如一个立方体osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f), 1.0f));osg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(shape);// 将几何体添加到MatrixTransform节点transform->addChild(geode);// 创建旋转回调并添加到节点transform->setUpdateCallback(new RotateCallback(0.5f));// 创建场景图的根节点osg::ref_ptr<osg::Group> root = new osg::Group;root->addChild(transform);// 设置场景数据viewer.setSceneData(root);// 运行Viewerreturn viewer.run();
}

运行效果

在这里插入图片描述

实现位移动画的TranslateCallback

嗯,继续上代码,一切都在代码里。

#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/MatrixTransform>
#include <osg/NodeCallback>
#include <osgViewer/Viewer>
#include <osg/FrameStamp>
#include <osg/ShapeDrawable>
#include <osgDB/ReadFile>
#include <iostream>
#include <cstdlib>class TranslateCallback : public osg::NodeCallback
{
public:TranslateCallback(const osg::Vec3& direction, float speed, float boundary) : _direction(direction), _speed(speed), _boundary(boundary), _reverse(false) {}virtual void operator()(osg::Node* node, osg::NodeVisitor* nv){// 转换为MatrixTransform节点osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);if (transform){// 计算时间间隔// double deltaTime = nv->getFrameStamp()->getSimulationTime() - _lastTime;// _lastTime = nv->getFrameStamp()->getSimulationTime();// 根据是否反转来确定方向osg::Vec3 currentDirection = _reverse ? -_direction : _direction;// osg::Vec3 currentDirection = _direction;// 计算位移量osg::Vec3 translation = currentDirection * _speed;// 获取当前矩阵osg::Matrix matrix = transform->getMatrix();// 更新矩阵的位移部分matrix.postMultTranslate(translation);transform->setMatrix(matrix);// 获取当前位置osg::Vec3 currentPosition = matrix.getTrans();float dotProduct  = std::abs(currentPosition * currentDirection);std::cout<< "  dotProduct=" << dotProduct<<std::endl;// 判断是否到达边界if (dotProduct >= _boundary || dotProduct <= 0){_reverse = !_reverse;}}// 继续遍历子节点traverse(node, nv);}private:osg::Vec3 _direction;  // 位移方向float _speed;          // 位移速度float _boundary;       // 边界距离bool _reverse;         // 是否反转方向double _lastTime = 0.0;  // 上一帧的时间};int main(int argc, char** argv)
{// 初始化 OpenSceneGraph 的默认设置osg::ArgumentParser arguments(&argc, argv);// 禁用着色器管道osg::DisplaySettings::instance().get()->setShaderPipeline(false);// 创建三个 MatrixTransform 节点,分别代表三个模型osg::ref_ptr<osg::MatrixTransform> transform1 = new osg::MatrixTransform;osg::ref_ptr<osg::MatrixTransform> transform2 = new osg::MatrixTransform;osg::ref_ptr<osg::MatrixTransform> transform3 = new osg::MatrixTransform;// 设置初始变换矩阵(可选)transform1->setMatrix(osg::Matrix::translate(osg::Vec3(-200.0f, 100.0f, 0.0f)));transform2->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 100.0f, 0.0f)));  // 调整Y轴位置transform3->setMatrix(osg::Matrix::translate(osg::Vec3(200.0f, 100.0f, 0.0f)));// 创建几何体(例如立方体、球体、圆柱体)osg::ref_ptr<osg::Geode> geode1 = new osg::Geode;geode1->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f), 100.0f)));  // 左边的立方体osg::ref_ptr<osg::Geode> geode2 = new osg::Geode;geode2->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 50.0f)));  // 中间的球体// 加载模型(支持.osg/.obj格式)osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../IronMan.osg");  // 替换为你的模型路径// 检查模型是否加载成功if (!model) {std::cerr << "模型加载失败!请检查路径和格式。" << std::endl;return 1;}// 将几何体添加到对应的变换节点transform1->addChild(geode1);transform2->addChild(geode2);transform3->addChild(model);// 为每个变换节点设置不同的 UpdateCallbacktransform1->setUpdateCallback(new TranslateCallback(osg::Vec3(0.0f, 0.0f, 1.0f), 1.0f, 200));  // 绕 Z 轴旋转,速度较慢transform2->setUpdateCallback(new TranslateCallback(osg::Vec3(0.0f, -1.0f, 0.0f), 1.0f, 100));  // 绕 X 轴旋转,速度中等transform3->setUpdateCallback(new TranslateCallback(osg::Vec3(1.0f, 0.0f, 0.0f), 1.0f, 400));  // 绕 Y 轴旋转,速度较快// 创建一个组节点,将三个变换节点添加到场景中osg::ref_ptr<osg::Group> root = new osg::Group;root->addChild(transform1);root->addChild(transform2);root->addChild(transform3);// 创建 Viewer 并设置场景数据osgViewer::Viewer viewer(arguments);viewer.setSceneData(root);// 运行 Viewerreturn viewer.run();
}

运行效果

在这里插入图片描述
钢铁侠今天也累了,下课。_

在这里插入图片描述

http://www.xdnf.cn/news/200305.html

相关文章:

  • Vue 3 vuedraggable 例子
  • AI网文热门题材生成用什么?小说创作工具来帮忙
  • C++中的智能指针
  • 双向流-固计算前处理和耦合设置
  • tanstack动态路由 + router/ 目录管理方案
  • 树莓派学习专题<12>:使用x264库实施H264编码--Linux和Windows上的部署
  • OpenVLA-OFT
  • 谷歌政策松绑?!3月仅下架4.8万款App,同比减少50%
  • Spring生命周期
  • Linux系统编程---exec簇:进程的加载与替换
  • 安装qt4.8.7
  • 软件评测:从多维度看其界面、功能、性能稳定性如何?
  • Java后端开发day38--不可变集合Stream流
  • Java后端接口调用拦截处理:注解与拦截器的实现
  • STM32实现SPI转USB虚拟串口输出(实测40M时钟不丢包)
  • 报表工具:企业数据决策的“智能翻译官“
  • 【knife4j】添加Cookie
  • 12. RANSAC点云多平面拟合分割
  • MySQL5.7.21查询入门
  • 软链接与硬链接
  • Transformer Prefill阶段并行计算:本质、流程与思考
  • 电价单位解析与用电设备耗电成本计算
  • python程序设习题答案
  • 沐曦玩转 LMDeploy、XTuner 和 InternLM3
  • es2025新特性
  • lmms-eval--微调实战笔记
  • 2.2.2goweb内置的 HTTP 处理程序2
  • Nature Communications 仿生电子天线:赋予机器人敏锐 “触觉”
  • TimDbg
  • AT2401C与RFX2401C问题处理资料