当前位置: 首页 > 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();
}

运行效果

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

在这里插入图片描述

相关文章:

  • 基于单片机的游泳馆智能管理系统设计与实现
  • shell--数组、正则表达式RE
  • PostgreSQL与MySQL哪个适合做时空数据分析?
  • Foupk3systemX5OS系统产品设备
  • 2025系统架构师---论微服务架构及其应用
  • MCU内存映射技术详解
  • 【专题四】前缀和(3)
  • 升级Xcode16,flutter项目报错
  • 实现分页的几种方法
  • Field访问对象int字段,对象访问int字段,通过openjdk17 C++源码看对象字段访问原理
  • 97AB-ASEMI机器人功率器件专用97AB
  • 模型上下文协议(MCP)深度解析:大模型从“思考者“进化为“行动者“
  • 01 C++概述
  • 2025 SAP专精特新企业高峰论坛 | 工博科技以SAP公有云+AI赋能新质生产力​
  • 15、项目搭建:绘制城堡蓝图——React 19 工程配置
  • 在android 系统上qnn sdk转换,运行模型示例
  • Shell脚本-嵌套循环应用案例
  • 塔能科技:点亮节能之光,赋能工厂与城市
  • 013几何数学——算法备赛
  • 科技助力防灾减灾:卫星电话走进应急救援队伍
  • 广西干旱程度有所缓解,未来一周旱情偏重地区降水量仍不足
  • 文化润疆|让新疆青少年成为“小小博物家”
  • 央行副行长:研究建立民营中小企业增信制度,破解民营中小企业信用不足等融资制约
  • 清华姚班,正走出一支军团
  • 中日友好医院通报“医师肖某被举报”:基本属实,开除党籍并解聘
  • 传染病防治法修订草案提请三审,拟加强医疗机构疾控能力建设