OSG 学习第一天:场景的组织及渲染

OSG 场景的组织及渲染

前言:翻开导师给的OSG学习资料,打开各个参考书。如《OpenSceneGraph三维渲染引擎编程指南 》、《OpenSceneGraph程序开发指南 》。发现osgChina是十年前从我们实验室走出去的,看着大师兄们留下的资料感觉无比的荣幸;看着他们最初的奋斗历程异常艰辛,他们是多么的努力多么对学习充满激情,深感自愧不如。
有意愿了解osg在中国的朋友,可以登录 osgChina 查看。

本文参照:《OpenSceneGraph三维渲染引擎编程指南 》


1.Geode
osg::Geode是OSG中的叶节点,用于保存几何信息以便渲染。同时,作为叶节点,它就不会再包含子节点。在应用程序中,所有相关的几何体的渲染都必须与Geode节点相关联。

类说明:Geode 结点,是个几何结点,可以说是一个几何 Group 结点,一般的可绘制几何体都是通过它来 传向 root 进行渲染。是 OSG 几何绘制的最高管理结点。 

类继承图:
 
 

1.1布告板示例
Billboard节点继承自Geode节点,因此它是一个叶节点,不可再包含其他的子节点,只能像叶节点那样通过添加Drawable 来绘制信息。Billboard 有下面3种模式:
enum   Moda
{
      POINT_ROT_EYE; //绕视点
      POINT_ROT_WORLD;  //绕世界坐标
      AXIAL_ROT;     //绕轴
}
说白了,布告板就是相当于纹理贴图。下面附上一段书中代码:
#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>


osg::ref_ptr<osg::Node> createBillboardTree(osg::ref_ptr<osg::Image> image)
{
	//创建四边形
	osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();

	//设置顶点
	osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
	v->push_back(osg::Vec3(-0.5f,0.0f,-0.5f));
	v->push_back(osg::Vec3(0.5f,0.0f,-0.5f));
	v->push_back(osg::Vec3(0.5f,0.0f,0.5f));
	v->push_back(osg::Vec3(-0.5f,0.0f,0.5f));

	geometry->setVertexArray(v.get());

	//设置法线
	osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array();
	normal->push_back(osg::Vec3(1.0f,0.0f,0.0f)^osg::Vec3(0.0f,0.0f,1.0f));

	geometry->setNormalArray(normal.get());
	geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);

	//设置纹理坐标
	osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
	vt->push_back(osg::Vec2(0.0f,0.0f));
	vt->push_back(osg::Vec2(1.0f,0.0f));
	vt->push_back(osg::Vec2(1.0f,1.0f));
	vt->push_back(osg::Vec2(0.0f,1.0f));

	geometry->setTexCoordArray(0,vt.get());

	//绘制四边形
	geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));

	if (image.get())
	{
		//状态属性对象
		osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();

		//创建一个Texture2D属性对象
		osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();

		//关联image
		texture->setImage(image.get());
		//关联Texture2D纹理对象,第三个参数默认为ON
		stateset->setAssociatedTextureModes(0,texture,osg::StateAttribute::ON);

		//启用混合
		stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
		//关闭光照
		stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

		geometry->setStateSet(stateset.get());
	}

	//创建Billbroad 对象一
	osg::ref_ptr<osg::Billboard> billbroad1 = new osg::Billboard();

	//设置旋转模式为绕视点
	billbroad1->setMode(osg::Billboard::POINT_ROT_EYE);
	//添加Drawable,并设置其位置,默认位置为osg::Vec3(0.0f,0.0f,0.0f)
	billbroad1->addDrawable(geometry.get(),osg::Vec3(5.0f,0.0f,0.0f));

	osg::ref_ptr<osg::Billboard> billbroad2 = new osg::Billboard();
	//设置旋转模式为绕轴转,因此还需要设置旋转轴
	billbroad2->setMode(osg::Billboard::AXIAL_ROT);
	//设置旋转轴
	billbroad2->setAxis(osg::Vec3(0.0f,0.0f,1.0f));
	billbroad2->addDrawable(geometry.get(),osg::Vec3(10.0f,0.0f,0.0f));

	osg::ref_ptr<osg::Group> billbroad = new osg::Group();
	billbroad->addChild(billbroad1.get());
	billbroad->addChild(billbroad2.get());

	return billbroad.get();
}

int main()
{
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

	osg::ref_ptr<osg::Group> root = new osg::Group();

	//读取图像
	osg::ref_ptr<osg::Image> image = osgDB::readImageFile("Images/tree0.rgba");

	//缩放,达到合适的大小
	osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();
	pat->setScale(osg::Vec3(5.0f,5.0f,5.0f));
	pat->addChild(createBillboardTree(image.get()));

	root->addChild(pat.get());

	//读取cow的模型,进行对比
	root->addChild(osgDB::readNodeFile("cow.osg"));

	//优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	viewer->setSceneData(root.get());

	viewer->realize();

	viewer->run();

	return 0;
}

1.  建立新的Geometry实例,用于输入顶点,颜色等数据的osg::Vec3Array,osg::Vec4Array变量数组,以及用于建立点索引的osg::UByteArray,osg:: IntArray等。示例代码如下:
osg::ref_ptr<osg::Geometry> geo = new osg::Geometry;
osg::Vec3Array* vecarray = new osg::Vec3Array;     //顶点坐标数组
osg::UByteArray* vecindex = new osg::UByteArray;   //顶点索引数组
osg::Vec4Array* colarray = new osg::Vec4Array;     //颜色RGB值数组
osg::UByteArray* colindex = new osg::UByteArray;   //颜色索引数组
osg::Vec3Array* norarray = new osg::Vec3Array;     //法线坐标数组
osg::UByteArray* norindex = new osg::UByteArray;   //法线索引数组 

 2.向顶点坐标变量数组中输入顶点数据,osg::Vec3Array是一个模板类,继承自STL的vector,因此可以使用push_back方法送入osg::Vec3的坐标数据。颜色数据,法线坐标数据的保存与此类似,不过一般来说颜色数据使用osg::Vec4Array加以保存,除了RGB值之外,还包括一个Alpha分量。示例代码如下:
vecarray->push_back(osg::Vec3(1.0, 0.0, 1.0));
vecarray->push_back(osg::Vec3(-1.0, 0.0, 1.0));
vecarray->push_back(osg::Vec3(-1.0, 0.0, -1.0));
vecarray->push_back(osg::Vec3(1.0, 0.0, -1.0));
 
colarray->push_back(osg::Vec4(1.0, 0.0, 0.0, 1.0));    //Red
colarray->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));    //Green
colarray->push_back(osg::Vec4(0.0, 0.0, 1.0, 1.0));    //Blue
colarray->push_back(osg::Vec4(1.0, 1.0, 1.0, 1.0));    //White
 
norarray->push_back(osg::Vec3(0.0, -1.0, 0.0));


2.Group
类描述:对结点起到组织作用,一般做为父结点或者根结点出现。它允许有一系列的孩子,相同的孩子或 者孩子之间有引用重得加入的会共享内存,是通过父类 osg::Referenced 实现自动管理内存句柄的。
类继承图: 
 

附上Group 的子类程序,位置变换节点示例:
#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/PositionAttitudeTransform>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

int main()
{
	//创建Viewer对象,场景浏览器
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

	//创建场景组节点
	osg::ref_ptr<osg::Group> root = new osg::Group();

	//创建一个节点,读取牛的模型
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");

	//创建位置变化节点 pat1
	osg::ref_ptr<osg::PositionAttitudeTransform> pat1 = new osg::PositionAttitudeTransform();
	//设置位置为osg::Vec3(-10.0f, 0.0f, 0.0f)
	pat1->setPosition(osg::Vec3(-10.0f, 0.0f, 0.0f));
	//设置缩放,在X.Y.Z方向都缩小一倍
	pat1->setScale(osg::Vec3(0.5f, 0.5f, 0.5f));
	//添加子节点
	pat1->addChild(node.get());

	//创建位置变换节点pat2
	osg::ref_ptr<osg::PositionAttitudeTransform> pat2 = new osg::PositionAttitudeTransform();
	pat2->setPosition(osg::Vec3(10.0f, 0.0f, 0.0f));
	pat2->addChild(node.get());

	//添加到场景
	root->addChild(pat1.get());
	root->addChild(pat2.get());

	//优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	//设置场景数据
	viewer->setSceneData(root.get());
	//初始化并创建窗口
	viewer->realize();
	//开始渲染
	viewer->run();

	return 0;
}


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值