OSG学习:空间变换节点和开关节点示例

以下内容来自: 

1、《OpenSceneGraph三维渲染引擎设计与实践》王锐 钱学雷 清华大学出版社

2、自己的总结

下载完整工程OSG_1_NodeTransform、OSG_2_NodeSwitch

创建C++项目后,首先需要配置OSG环境。具体步骤看OSG学习:WIN10系统下OSG+VS2017编译及运行第六步:新建OSG项目测试

1.空间变换节点

根据用户视点自动进行变换的AutoTransform节点;

直接使用矩阵进行变换的MatrixTransform节点;

使用位移、旋转和缩放值进行变换的PositionAttitudeTransform节点。

// stdafx.h

#include <osg/AutoTransform> //自动变换节点类,使节点自动对齐于摄像机或屏幕。
#include <osg/MatrixTransform> //移动节点的矩阵类,最常用的移动节点的类。可随动、旋转控制节点。
#include <osg/PositionAttitudeTransform> //位置变换节点类,提供模型的位置变换、大小缩放、原点位置的设置、坐标系的变换
#include <osgViewer/Viewer> //视窗管理库,显示场景。为单独的场景保存一个单独的view,每个单独场景的程序都有一个Viewer
#include <osgDB/ReadFile> //数据读写库
//.cpp

#include "stdafx.h"

/*创建自动变换节点对象AutoTransform,使其始终面对屏幕,即用户视点*/
osg::Transform *createAutoTransform(double posX, osg::Node *model)
{
	//在osg智能指针中进行定义
	osg::ref_ptr<osg::AutoTransform> at = new osg::AutoTransform;
	at->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN); //设置自动变换模式,始终面对屏幕
	at->setPosition(osg::Vec3(posX, 0.0, 0.0)); //设置模型的位置
	at->addChild(model);
	//新建对象作为函数结果返回时,应该返回release(),并尽快引入到别的场景中,否则发生内存泄露
	return at.release();
}

/*创建空间变换矩阵节点对象MatrixTransform,并使其沿Z轴逆时针旋转45度*/
osg::Transform *createMatrixTransform(double posX, double rotateZ, osg::Node *model)
{
	//在osg智能指针中进行定义
	osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
	//设置空间变换矩阵的内容,格式都为setMatrix(osg::Matrix::translate(x, y, z)),其中osg::Matrix::Scale和osg::Matrix::rotate也可以被用在其中,并且可以相乘叠加
	//设置mat矩阵后把node加入到mat中,再把mat加入到Group中,在这个例子中model在main函数中就已加入到Group中了
	mt->setMatrix(osg::Matrix::rotate(rotateZ, osg::Z_AXIS) *osg::Matrix::translate(posX, 0.0, 0.0));
	mt->addChild(model);
	//新建对象作为函数结果返回时,应该返回release(),并尽快引入到别的场景中,否则发生内存泄露
	return mt.release();
}

/*创建位置姿态节点对象PositionAttitudeTransform,使其沿Z轴顺时针旋转45度*/
osg::Transform *createPositionAttitudeTransform(double posX, double rotateZ, osg::Node *model)
{
	//在osg智能指针中进行定义
	osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
	pat->setPosition(osg::Vec3(posX, 0.0, 0.0));
	pat->setAttitude(osg::Quat(rotateZ, osg::Z_AXIS));
	pat->addChild(model);
	//新建对象作为函数结果返回时,应该返回release(),并尽快引入到别的场景中,否则发生内存泄露
	return pat.release();
}

int main(int argc, char **argv)
{
	//读取main函数参数以及外部参数的类,会自动识别外部参数正确与否
	//它是一个单独的类
	//ArgumentParser(int *argc, char **argv)构造函数,传入参数为main的两个参数,前者代表命令行参数个数,后者代表参数的具体值
	osg::ArgumentParser arguments(&argc, argv);
	//如果外部参数正确,则使用osgDB::readNodeFile读取该模型,否则读取本地坐标系模型文件axes.osgt
	osg::Node *model = osgDB::readNodeFiles(arguments);
	if (!model)
		model = osgDB::readNodeFile("axes.osgt");

	//将3个节点加入到场景根节点中,同时它们的子节点均为一个预设的模型节点model,因此实现了场景中叶节点的共享
	osg::ref_ptr<osg::Group> root = new osg::Group;
	//把新创建的节点加入到Group中
	root->addChild(createMatrixTransform(-5.0, osg::PI / 4, model));
	root->addChild(createAutoTransform(0.0, model));
	root->addChild(createPositionAttitudeTransform(5.0, -osg::PI / 4, model));

	//实例化显示图像的类osgViewer::Viewer
	osgViewer::Viewer viewer;
	//设置viewer显示的场景
	viewer.setSceneData(root.get());
	//开始执行渲染操作,返回值一般为1,程序退出或出错返回0
	return viewer.run();
}

2、开关节点

// stdafx.h

#include <osg/Switch> //控制子类的显示与隐藏,这种隐藏不消耗内存
#include <osgViewer/Viewer> //视窗管理库,显示场景。为单独的场景保存一个单独的view,每个单独场景的程序都有一个Viewer
#include <osgDB/ReadFile> //数据读写库
//.cpp

#include "stdafx.h"

/*从NodeCallback类派生,并重构执行函数operator(),实现自定义的节点回调功能
定义名为CessnaCallback的节点更新回调,它使用getFrameNumber()随时取得当前的运行帧数
当帧数大于预先设定的切换值120时,使用setValue()执行子节点的切换*/
class CessnaCallback :public osg::NodeCallback
{
public:
	static const int _fireStartFrame = 120; //起火开始时间,即切换模型时的运行帧数,秒

	//虚函数。当回调动作发生时,将会执行这一操作符的内容,并将节点和访问器对象作为参数传入
	//重载第一个(),而(osg::Node *node, osg::NodeVisitor *nv)是该重载函数的参数表,前者为场景节点,后者为访问器对象,即访问器当前访问的节点
	virtual void operator()(osg::Node *node, osg::NodeVisitor *nv)
	{
		//dynamic_cast将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理
		//dynamic_cast <type-id> (expression) 该运算符把expression转换成type-id类型的对象,Type-id 必须是类的指针、类的引用或者void*,它可以在执行期决定真正的类型
		//如果type-id是类指针类型,那么expression也必须是一个指针,如果 type-id 是一个引用,那么 expression 也必须是一个引用
		//dynamic_cast主要用于类层次间的上行转换(和static_cast效果一样)和下行转换(具有类型检查的功能,比static_cast更安全),还可以用于类之间的交叉转换
		osg::Switch *cessnaSwitch = dynamic_cast<osg::Switch *>(node); 
		if (cessnaSwitch &&nv)
		{
			//实例化类osg::FrameStamp
			//getFrameStamp()获取节点的帧数信息
			const osg::FrameStamp *frameStamp = nv->getFrameStamp();
			if (frameStamp)
			{
				//比较起火时的帧数和当前帧数,120帧以后关闭飞机模型cessna.osg开启起火后飞机模型cessnafire.osg
				if (_fireStartFrame < frameStamp->getFrameNumber()) //获取上一帧的帧号,即时间,秒
				{
					//setValue()执行子节点的切换
					cessnaSwitch->setValue(0, false);
					cessnaSwitch->setValue(1, true);
				}
			}
		}
		traverse(node, nv); //向下一个需要访问的节点推进
	}
};

int main(int argc, char **argv)
{
	//在osg智能指针中定义开关节点
	osg::ref_ptr<osg::Switch> root = new osg::Switch;
	//读取模型并将之添加到开关节点中
	//默认开启子节点飞机模型cessna.osg,默认关闭(切换后开启)子节点起火后的飞机模型cessnafire.osg
	root->addChild(osgDB::readNodeFile("cessna.osg"), true);
	root->addChild(osgDB::readNodeFile("cessnafire.osg"), false);
	//setUpdateCallback自定义回调类CessnaCallback作为更新回调传递给节点,设置人机交互回调为node->setEventCallback(new CessnaCallback)
	root->setUpdateCallback(new CessnaCallback);

	//实例化显示图像的类osgViewer::Viewer
	osgViewer::Viewer viewer;
	//设置viewer显示的场景
	viewer.setSceneData(root.get());
	//开始执行渲染操作,返回值一般为1,程序退出或出错返回0
	return viewer.run();
}

 

 

第1章 OpenSceneGraph概述 1.1 OpenSceneGraph简介 1.1.1 什么是OpenSceneGraph 1.1.2 OpenSceneGraph的历史和发展 1.1.3 OSG中国 1.1.4 OSG组成模块 1.2 发的预备知识 1.3 OSG的安装及编译 1.3.1 OSG的获取及安装 1.3.2 编译OSG 1.3.3 OSG邮件列表 1.4 OSG基础 1.4.1 发环境设置 1.4.2 OSG中的HelloWorld工程 1.4.3 OSG实用工具——场景浏览器osgViewer 1.4.4 OSG实用工具——版本信息查看器osgVersion 1.4.5 OSG实用工具——场景图形压缩归档工具osgArchive 1.4.6 OSG实用工具——数据转换工具osgConv 第2章 OpenSceneGraph数学基础 2.1 坐标系统 2.2 坐标系变换 2.2.1 世界坐标系-物体坐标系变换 2.2.2 物体坐标系-世界坐标系变换 2.2.3 世界坐标系-屏幕坐标系变换 2.3 向量、矩阵及四元数 2.3.1 向量 2.3.2 矩阵 2.3.3 四元数 2.3.4 矩阵与四元数之间的转换 第3章 场景的组织及渲染 3.1 OSG场景树 3.1.1 OSG场景树节点 3.1.2 OSG中的父节点与子节点 3.2 Geode 3.2.1 Billboard节点 3.2.2 布告板示例 3.3 Group 3.3.1 位置变换节点 3.3.2 位置变换节点示例 3.3.3 矩阵变换节点 3.3.4 矩阵变换节点示例 3.3.5 自动对齐节点 3.3.6 自动对齐节点示例 3.3.7 关节点 3.3.8 关节点示例 3.3.9 细节层次节点 3.3.10 细节层次节点示例 3.3.11 分页细节层次节点 3.3.12 分页细节层次节点示例 3.3.13 替代节点 3.3.14 替代节点示例 3.3.15 遮挡裁剪节点 3.3.16 遮挡裁剪节点示例 3.3.17 坐标系节点 3.3.18 坐标系节点示例 3.4 场景中节点的拷贝——osg::CopyOp类 3.4.1 自定义场景拷贝示例(一) 3.4.2 自定义场景拷贝示例(二) 第4章 OSG中几何体的绘制 第5章 渲染状态、纹理与光照 第6章 文件的读写 第7章 场景图形的工作机制 第8章 场景图形管理 第9章 OSG文字 第10章 OSG动画与声音 第12章 osgFX扩展库及osgSim扩展库 第13章 OSG地形与地理信息 参考文献
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值