OSG动画与声音-动画(3)

news2024/9/27 23:23:55

动画

        动画是一种常见的动画形式(Frame ByFrame),其原理是在连续的关键帧中分解动画动作,从另一个方面来说,也就是在时间轴的每帧上逐顿绘制不同的内容,使其连续播放而形成动画。

        因为帧动画的帧序列内容不一样,不但给制作增加了负担,而且最终输出的文件量也很大,但它的优势也很明显:帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似于电影的播放模式,很适合于表演细腻的动画,如说话、飘动等。

osg::Sequence

        osg::Sequence类直接继承自osg::Group类它也可以作为一个组节点,继承关系图如图10-6所示。

图10-6 osg::Sequence 的继承关系图

        作为场景的一个组节点,它可以添加其他的节点。帧动画通常有图片帧动画模型帧动画文字帧动画3种。无论是哪种动画,在OSG中,都需要把它们做成一个节点示例添加到场景中。图片可以创建一个四边形纹理、文字可以添加到Geode示例,模型就可以直接添加。

        osg::Sequence 类主要负责动画的管理染操作,如加入节点、设置动画模式、设置动画状态及设置动画速度等。

        可以通过调用下面的函数设置帧动画的模式类型:

  1. void setInterval(LoopMode mode, int begin, int end)  
  2. // 第一个参数动画的模式类型,第二、三个参数分别是开始和终止时间  
  3. void getInterval(LoopMode &mode, int &begin, int &end) const  
  4. enum LoopMode  
  5. {  
  6.     LOOP//循环  
  7.     SWING//单摆  
  8. }  

        可以通过调用下面的函数设置帧动画的渲染状态模式

  1. void setMode(SequenceMode mode)  
  2. SequenceMode getMode 0 const  
  3. enum SequenceMode  
  4. {  
  5.     START,//开始  
  6.     STOP//停止  
  7.     PAUSE//暂停  
  8.     RESUME//继续  
  9. }  

        可以通过调用下面的函数设置帧动画的速度和重复次数:

  1. //第一个参数是动画的速度,第二个参数是重复次数,默认为-1(无限次)  
  2. void setDuration(float speed, int nreps = -1);  
  3. void getDuration(float &speed, int &nreps) const;  

        有时由于对帧动画的手动控制,可能导致帧动画不能与帧渲染时间一一对应,可以通过调用一个类的成员函数来完成与帧的同步,默认情况是不同步的,成员函数如下

  1. void setSync (bool sync)// 默认为 false  
  2. void getSync (bool &sync) const 

        在第10.2.2节的示例中会用到一系列的模型来演示一个动画,但只是教读者如何来创建和实现帧动画及其控制,在实际应用中需要使用更加精细的方法(在后面介绍自定义粒子系统时会讲到,要耐心阅读。

​​​​​​​动画显示与控制示例

        动画(osg::Sequcnce)显示与控制示例的代码如程序清单10-4所示

1.	/// 帧动画 //  
2.	// 对节点进行适当的缩放  
3.	osg::ref_ptr<osg::Node> createScaledNode(osg::ref_ptr<osg::Node>, float targetScale);  
4.	  
5.	// 创建帧动画  
6.	osg::ref_ptr<osg::Sequence> createSequenece(const string &strDataFolder);  
7.	  
8.	// 帧动画事件控制  
9.	class SequenceEventHandler :public osgGA::GUIEventHandler  
10.	{  
11.	public:  
12.	    // 构造函数  
13.	    SequenceEventHandler(osg::ref_ptr<osg::Sequence> seq)  
14.	    {  
15.	        _seq = seq;  
16.	    }  
17.	  
18.	    virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)  
19.	    {  
20.	        osg::Sequence::SequenceMode mode = _seq->getMode();  
21.	        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN)  
22.	        {  
23.	            switch (ea.getKey())  
24.	            {  
25.	                // 暂停  
26.	                case 'p':  
27.	                {  
28.	                    mode = osg::Sequence::PAUSE;  
29.	                    _seq->setMode(mode);  
30.	                    break;  
31.	                }  
32.	                // 开始  
33.	                case 's':  
34.	                {  
35.	                    mode = osg::Sequence::START;  
36.	                    _seq->setMode(mode);  
37.	                    break;  
38.	                }  
39.	                // 继续  
40.	                case 'r':  
41.	                {  
42.	                    mode = osg::Sequence::RESUME;  
43.	                    _seq->setMode(mode);  
44.	                    break;  
45.	                }  
46.	                // 停止  
47.	                case 'l':  
48.	                {  
49.	                    mode = osg::Sequence::STOP;  
50.	                    _seq->setMode(mode);  
51.	                    break;  
52.	                }  
53.	                default:  
54.	                    break;  
55.	            }  
56.	        }  
57.	  
58.	        return false;  
59.	    }  
60.	private:  
61.	    osg::ref_ptr<osg::Sequence> _seq;  
62.	};  
63.	  
64.	void sequence_10_4(const string &strDataFolder);  
65.	/// 帧动画 //  
66.	// 对节点进行适当的缩放  
67.	osg::ref_ptr<osg::Node> createScaledNode(osg::ref_ptr<osg::Node> node, float targetScale)  
68.	{  
69.	    // 通过包围盒确定合适的缩放  
70.	    const osg::BoundingSphere &bsphere = node->getBound();  
71.	    float scale = targetScale / bsphere._radius;  
72.	  
73.	    osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();  
74.	    pat->setPosition(osg::Vec3(0.0, 0.0, 0.0));  
75.	    pat->setScale(osg::Vec3(scale, scale, scale));  
76.	    pat->setDataVariance(osg::Object::DYNAMIC);  
77.	    pat->addChild(node.get());  
78.	  
79.	    // 法线归一化,保证光照明暗均匀  
80.	    osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();  
81.	    stateset = pat->getOrCreateStateSet();  
82.	    stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);  
83.	  
84.	    return pat.get();  
85.	}  
86.	  
87.	// 创建帧动画  
88.	osg::ref_ptr<osg::Sequence> createSequenece(const string &strDataFolder)  
89.	{  
90.	    // 创建帧动画对象  
91.	    osg::ref_ptr<osg::Sequence> seq = new osg::Sequence;  
92.	  
93.	    // 文件名向量对象  
94.	    typedef std::vector<std::string> Filenames;  
95.	    Filenames filenames;  
96.	  
97.	    // 添加模型名  
98.	    filenames.push_back(strDataFolder + "cow.osg");  
99.	    filenames.push_back(strDataFolder + "spaceship.osg");  
100.	    filenames.push_back(strDataFolder + "dumptruck.osg");  
101.	    filenames.push_back(strDataFolder + "cessna.osg");  
102.	    filenames.push_back(strDataFolder + "glider.osg");  
103.	  
104.	    for (Filenames::iterator itr = filenames.begin(); itr != filenames.end(); ++itr)  
105.	    {  
106.	        // 加载模型  
107.	        osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(*itr);  
108.	        if (node)  
109.	        {  
110.	            // 添加子节点  
111.	            seq->addChild(createScaledNode(node, 100.0));  
112.	  
113.	            // 设置节点的持续时间  
114.	            seq->setTime(seq->getNumChildren() - 1, 1.0);  
115.	        }  
116.	    }  
117.	  
118.	    // 设置帧动画持续的时间  
119.	    seq->setInterval(osg::Sequence::LOOP, 0, -1);  
120.	  
121.	    // 设置播放的速度及重复的次数  
122.	    seq->setDuration(1.0, -1);  
123.	  
124.	    // 开始播放  
125.	    seq->setMode(osg::Sequence::START);  
126.	  
127.	    return seq.get();  
128.	}  
129.	  
130.	void sequence_10_4(const string &strDataFolder)  
131.	{  
132.	    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();  
133.	    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
134.	    traits->x = 40;  
135.	    traits->y = 40;  
136.	    traits->width = 600;  
137.	    traits->height = 480;  
138.	    traits->windowDecoration = true;  
139.	    traits->doubleBuffer = true;  
140.	    traits->sharedContext = 0;  
141.	  
142.	    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());  
143.	  
144.	    osg::ref_ptr<osg::Camera> camera = viewer->getCamera();  
145.	    camera->setGraphicsContext(gc.get());  
146.	    camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));  
147.	    GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;  
148.	    camera->setDrawBuffer(buffer);  
149.	    camera->setReadBuffer(buffer);  
150.	  
151.	    osg::ref_ptr<osg::Group> root = new osg::Group();  
152.	  
153.	    // 向场景中添加帧动画  
154.	    osg::ref_ptr<osg::Sequence> sq = new osg::Sequence();  
155.	    sq = createSequenece(strDataFolder);  
156.	  
157.	    root->addChild(sq.get());  
158.	  
159.	    // 添加帧动画控制事件  
160.	    viewer->addEventHandler(new SequenceEventHandler(sq.get()));  
161.	  
162.	    osgUtil::Optimizer optimize;  
163.	    optimize.optimize(root.get());  
164.	  
165.	    viewer->setSceneData(root.get());  
166.	  
167.	    viewer->realize();  
168.	  
169.	    viewer->run();  
170.	}  

        运行程序,截图如图 10-7 所示

图10-7 动画显示与控制示例截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1243094.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过 OGNL 注入执行 Confluence 预身份验证远程代码 (CVE-2022-26134)

漏洞描述 Confluence 是由澳大利亚软件公司 Atlassian 开发的基于 Web 的企业 wiki。 02 年 2022 月 <> 日&#xff0c;Atlassian 发布了针对其 Confluence Server 和 Data Center 应用程序的安全公告&#xff0c;强调了一个严重严重的未经身份验证的远程代码执行漏洞。…

java项目之网络在线考试系统(ssm)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的网络在线考试系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; &#xff08;1&#xff09;登录…

python如何快速查找到想要的文档

字多不看版&#xff0c;直接体验 待补充 演示代码 # -*- coding:UTF-8 -*-# region 导入必要的依赖包 import os import subprocess from enum import Enum模块名 pyperclip try:import pyperclip # 需要安装 pyperclip 模块&#xff0c;以支持粘贴板操作 except ImportEr…

Java零基础——SpringMVC篇

1.SpringMVC介绍 SpringMVC是Spring框架中的一个组件&#xff0c;是一个轻量级的web的MVC框架&#xff0c;充当controller,其本质就是一个Servlet。 1.1 传统Servlet的不足 每个请求&#xff0c;都需要定义一个Servlet。虽然可以在service方法中&#xff0c;根据业务标识进行…

「Verilog学习笔记」 输入序列不连续的序列检测

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 题目要求检测a的序列&#xff0c;a为单bit输入&#xff0c;每个时刻可能具有不同的值&#xff0c;且并不是每一个数据都是有效的&#xff0c;需要根据data_valid信号进行判…

【knife4j-spring-boot】Springboot + knife4j-spring-boot 整合swagger脚手架

swagger-boostrap-ui从1.x版本到如今2.x&#xff0c;同时也更改名字Knife4j 在此记录下 knife4j-spring-boot-starter 的整合。 只需要引入knife4j-spring-boot-starter&#xff0c;无需引入其他的swagger包&#xff0c;knife4j-spring-boot-starter已经包含。 官方版本说明…

软件系统测试有哪些测试流程?系统测试报告编写注意事项

在软件开发的过程中&#xff0c;系统测试是至关重要的一环&#xff0c;它的目的是验证和评估软件产品是否符合预期的质量标准&#xff0c;以确保系统的稳定性、可靠性和安全性。 一、软件系统测试的测试流程 1、需求分析与测试计划制定&#xff1a;根据需求分析确定测试目标、…

C++ 问题 怎么在C++11标准语法中调用C++20的类

一. 问题 在工作中,因为一个算法功能需要跟别的部门对接,他们提供了该算法的头文件.h,静态库.lib,动态库.dll。但是头文件中使用了C++20才有的新特性,如#include等,而本地使用的vs2015开发环境,只支持C++11标准语法,这种情况下,该怎么把该算法集成到本地项目中呢? …

前端已死?看看我的秋招上岸历程

背景 求职方向&#xff1a;web前端 技术栈&#xff1a;vue2、springboot&#xff08;学校开过课&#xff0c;简单的学习过&#xff09; 实习经历&#xff1a;两段&#xff0c;但都是实训类的&#xff0c;说白了就是类似培训&#xff0c;每次面试官问起时我也会坦诚交代&…

激光切割设备中模组的作用有哪些?

激光切割设备是一种高精度的自动化加工设备&#xff0c;用于对金属、非金属等材料进行精确切割。直线模组作为激光切割设备的重要组成部分&#xff0c;在激光切割设备中起着重要的作用&#xff0c;为设备的运动系统提供了高精度、高稳定性和高效率的运动控制。 1、高精度的位置…

【C++初阶】第一站:C++入门基础(中)

前言&#xff1a; 这篇文章是c入门基础的第一站的中篇,涉及的知识点 函数重载:函数重载的原理--名字修饰 引用:概念、特性、使用场景、常引用、传值、传引用效率比较的知识点 目录 5. 函数重载 &#xff08;续&#xff09; C支持函数重载的原理--名字修饰(name Mangling) 为什么…

【C语言】qsort函数

目录 简介 头文件 ​编辑 函数原型&#xff1a; 参数函数如何写&#xff1a; 参数函数要求&#xff1a; qsort对整性数据的排序&#xff1a; qsort对字符型数据的排序&#xff1a; 对结构体类型的内部元素排序&#xff1a; 函数的底层是以快速排序实现的 但是本文不深入…

关于「光学神经网络」的一切:理论、应用与发展

/目录/ 一、线性运算的光学实现 1.1. 光学矩阵乘法器 1.2. 光的衍射实现线性运行 1.3. 基于Rayleigh-Sommerfeld方程的实现方法 1.4. 基于傅立叶变换的实现 1.5. 通过光干涉实现线性操作 1.6. 光的散射实现线性运行 1.7. 波分复用&#xff08;WDM&#xff09;实现线性运…

phpstudy和IDEA 配置php debug

1.安装xdebug 扩展&#xff0c;phpinfo() 查看 2.配置php.ini zend_extensionD:/phpstudy_pro/Extensions/php/php7.4.3nts/ext/php_xdebug.dll xdebug.collect_params1 xdebug.collect_return1 xdebug.auto_traceOn xdebug.trace_output_dirD:/phpstudy_pro/Extensions/php_l…

vue + docxtemplater 导出 word 文档

一、痛点 word 导出 这种功能其实之前都是后端实现的&#xff0c;但最近有个项目没得后端。所以研究下前端导出。 ps&#xff1a; 前端还可以导出 pdf&#xff0c;但是其分页问题需要话精力去计算才可能实现&#xff0c;并且都不是很完善。可参考之前的文章&#xff1a;利用 h…

Flink 替换 Logstash 解决日志收集丢失问题

在某客户日志数据迁移到火山引擎使用 ELK 生态的案例中&#xff0c;由于客户反馈之前 Logstash 经常发生数据丢失和收集性能较差的使用痛点&#xff0c;我们尝试使用 Flink 替代了传统的 Logstash 来作为日志数据解析、转换以及写入 ElasticSearch 的组件&#xff0c;得到了该客…

PasteNow for mac剪贴板工具

PasteNow 是一款简单易用的剪贴板管理工具&#xff0c;可帮助用户快速存储和管理剪贴板上的文本和图片内容。用户可以使用 PasteNow 软件快速将文本内容保存到不同的笔记或页面中&#xff0c;也可以方便地将剪贴板上的图片保存到本地或分享给其他应用程序。 此外&#xff0c;P…

Java互联网+医院智能导诊系统源码 自动兼容H5小程序、Uniapp

随着信息和通信技术的进步,智能和移动技术越来越普遍,尤其在医疗保健领域,一些新型卫生信息系统被不断开发出来支持医院和其他卫生保健组织的管理和运作。 智能导诊系统是嵌入到医院和医疗保健卫生中心 HIS系统中的一种专门导诊系统,通过智能语音交互的方式帮助用户完成导诊、分…

XC2303 PFM 升压 DC-DC 变换器 SOT23-3封装 体积小 外围简单 适合小电流产品

XC2303系列产品是一种高效率、低纹波、工作频率高的 PFM 升压 DC-DC 变换器。XC2303系列产品仅需要四个元器,就可完成将低输入的电池电压变换升压到所需的工作电压&#xff0c;非常适合于便携式1~4 节普通电池应用的场合。 电路采用了高性能、低功耗的参考电压电路结构&#xf…

深度学习常见激活函数:ReLU,sigmoid,Tanh,softmax,Leaky ReLU,PReLU,ELU整理集合,应用场景选择

文章目录 1、ReLU 函数&#xff08;隐藏层中是一个常用的默认选择&#xff09;1.1 优点1.2 缺点 2、sigmoid 函数2.1 优点2.2 缺点 3、Tanh 函数3.1 优点3.2 缺点 4、softmax 函数&#xff08;多分类任务最后一层都会使用&#xff09;5、Leaky ReLU 函数5.1 优点5.2 缺点 6、PR…