构建几何图形
保存要渲染的数据
//osg::Vec3 是一个三维浮点数数组;可以用来保存顶点和法线数据;
//osg::Vec4用于保存颜色数据;而 osg::Vec2 可以用于保存 2D 纹理坐标。
//模板数组:osg::Vec2Array,osg::Vec3Array 以及
//osg::Vec4Array(数组中的每一个数据如osg::Vec3())
osg::ref_ptr<osg::Node> createSceneGraph()
{
// 创建一个用于保存几何信息的对象
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// 创建四个顶点的数组
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
geom->setVertexArray(v.get()); //将v设置为顶点数组
v->push_back(osg::Vec3(-1.f, 0.f, -1.f));
//为对应的顶点的xyz坐标创建独立的三元向量(Vec3),并将其压入对应数组
v->push_back(osg::Vec3(1.f, 0.f, -1.f));
v->push_back(osg::Vec3(1.f, 0.f, 1.f));
v->push_back(osg::Vec3(-1.f, 0.f, 1.f));
// 创建四种颜色的数组
osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
geom->setColorArray(c.get()); //创建颜色数组
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
//设置Geometry类中颜色的绑定方式,
//osg::Geometry::BIND_PER_VERTEX,即每种颜色对应一个顶点
c->push_back(osg::Vec4(1.f, 0.f, 0.f, 1.f)); //(r,g,b,透明度)
c->push_back(osg::Vec4(0.f, 1.f, 0.f, 1.f));
c->push_back(osg::Vec4(0.f, 0.f, 1.f, 1.f));
c->push_back(osg::Vec4(1.f, 1.f, 1.f, 1.f));
// 为唯一的法线创建一个数组
osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
geom->setNormalArray(n.get()); //创建法线数组
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
//设置Geometry类中颜色的绑定方式
//osg::Geometry::BIND_OVERALL,即整个 Geometry 几何体对应唯一的一个法线数据
n->push_back(osg::Vec3(0.f, -1.f, 0.f)); //设置法线
// 由保存的数据绘制四个顶点的多边形
geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
//addPrimitiveSet() - 这个方法用于设置 Geometry 类数据渲染的方法。
//其参数为一个osg::PrimitiveSet 指针
//(DrawArrays类为PrimitiveSet的子类之一)。
//PrimitiveSet 是一个无法直接实例化的虚基类。一个 Geometry 类
//可以添加多个 PrimtiveSet 对象。
//osg::DrawArrays() 第一个参数:确定 渲染的图形(QUADS四边形)
(osg::PrimitiveSet::POINTS点,osg::PrimitiveSet::TRIANGLE_STRIP三角形等)
//第二个参数是顶点数组中的要使用的第一个顶点的下标,而第三个参数是将要使用的顶点元素的总数
//OSG 定义了 osg::Drawable 类,用于保存要渲染的数据。
//Drawable 是一个无法直接实例化的虚基类,osg::Geometry是其子类之一
//setVertexArray()和 setNormalArray()均使用一个
//Vec3Array 指针作为输入参数,而
//setColorArray()使用一个 Vec4Array 指针
//Geode 类派生自 Node 类。(在定义上,所有的 OSG 节点均
派生自 Node 类。)
//向 Geode 类添加几何体(Drawable)并返回 Geode
osg::ref_ptr<osg::Geode> geode = new osg::Geode; //叶节点(Geode)
geode->addDrawable(geom.get()); //将渲染数据与节点绑定
return geode.get();
}
Drawables 类: 用于保存要渲染的数据,Drawable 是一个无法直接实例化的虚基类,osg::Geometry
是其子类之一。
osg::Geometry
的类方法:
-
setVertexArray(); setColorArray(); setNormalArray();
—用于指定顶点数组,颜色,以及法线数据,setVertexArray()
和setNormalArray()
均使用一个 Vec3Array 指针作为输入参数,而setColorArray()
使用一个 Vec4Array 指针。 -
setColorBinding()
和setNormalBinding()
—这些方法用于设置osg::Geometry
类中颜色和法线数据的绑定方式,颜色绑定方式为 osg::Geometry::BIND_PER_VERTEX,即每种颜色对应一个顶点。而法线的绑定方式为osg::Geometry::BIND_OVERALL,即整个 Geometry 几何体对应唯一的一个法线数据。 -
addPrimitiveSet() —这个方法用于设置
osg::Geometry
类数据渲染的方式(绘制方式),一个 Geometry 类可以添加多个 PrimtiveSet 对象。addPrimitiveSet()方法允许用户程序设定OSG如何绘制Geometry类保存的几何数据。
图元数组
PrimitiveSet类本身并不能记录顶点索引的信息,因此需要使用其派生类DrawArrays和DrawElements(两者都叫图元数组)。
DrawArrays类
osg::DrawArrays* array = new osg::DrawArrays(mode,first,count)
对于参数mode: osg::PrimitiveSet::图元类型
DrawElements类
osg::DrawElements* array = new osg::DrawElementsUInt(mode,first,count)
与DrawArrays类类似,但是不再传入顶点数组的要渲染的第一个点的下标和要渲染的顶点总个数,而是直接传入所有要渲染的顶点的下标。
优势: 用户可以自己选择要渲染的顶点,而DrawArrays类只能选择第一个要渲染的顶点的后面的一连串点。
DrawElements类的三个子类: DrawElementsUByte、DrawElementsUInt、DrawElementsUShort 表示要传入的索引(下标)值的数据类型不同。
快速法线生成工具
osgUtil::SmoothingVisitor类是OSG自带的一个快速法线生成工具,对于复杂图形的法线计算很方便。
引入头文件 #include<osgUtil/SmoothingVisitor>
调用:
osgUtil::SmoothingVisitor smv;
smv.smooth(保存绘制体的对象名)
图元纹理与属性
OSG将渲染状态分成两个部分,渲染属性(attribute)和渲染模式(mode)。
渲染属性也就是控制渲染特性的状态变量。例如,雾的颜色,或者Blend融合函数都是OSG的状态属性,渲染模式:例如纹理映射、灯光,
渲染模式是指渲染的某个功能,而渲染属性是这个功能的控制变量和参数
渲染状态(Rendering State)
用户的应用程序需要在osg::StateSet类
中设置渲染状态:
添加渲染属性:
//获取变量geom的StateSet指针。(geom是一个Geometry几何类对象,当然也可以是
//任何其它派生自Drawable和Node的对象)
osg::StateSet* state = geom->getOrCreateStateSet();
//创建并添加CullFace属性类。参数有FRONT,BACK,FRONT_AND_BACK,
//用于指定剔除表面是正面还是反面
osg::CullFace* cf = new osg::CullFace( osg::CullFace::BACK );
state->setAttribute( cf ); //将属性添加至gemo中
允许或禁止渲染模式:
//可以使用osg::StateSet::setMode()允许或禁止某种模式(渲染模式)
// 获取一个StateSet实例。
osg::StateSet* state = geom->getOrCreateStateSet();
// 允许这个StateSet的雾效模式。
state->setMode(GL_FOG, osg::StateAttribute::ON);
//第一个参数:openGL中的枚举量(这里是烟雾fog的意思),第二个输入参数可以是
//osg::StateAttribute::ON或osg::StateAttribute::OFF,表示该模式打开或关闭。
//OSG提供了一个简单的可以同时设置属性和模式的单一函数接口
//例如CullFace属性的对应模式为GL_CULL_FACE
//如果要将某个属性关联到一个StateSet,同时打开其对应模式的许可,
//那么可以使用osg::StateSet::setAttributeAndModes()方法
// 创建一个BlendFunc属性。
osg::BlendFunc* bf = new osg::BlendFunc();
// 关联BlendFunc并许可颜色融合模式
state->setAttributeAndMode(bf);
渲染属性与模式:
纹理和纹理属性
纹理简单来说就是将图片贴在模型表面,也可以理解为"皮肤"。
二维纹理通常为矩形,当遇见非矩形的模型时,往往需要手动设置纹理的各个顶点的坐标,这就叫纹理坐标。
OSG共有8个纹理映射通道,又叫纹理单元(0~7),每个纹理单元可以独立设置不同的纹理坐标,以同时实现不同的图像映射结果,达到多重纹理的效果。
osg::ref_ptr<osg::Vec2Array>texcoords = new osg::Vec2Array;
//纹理坐标数组
texcoords->push_back(……)
//存放纹理坐标
geom->setTexCoordArray(0,texcoords.get())
//为描绘体添加纹理坐标,参数1为用户选定的纹理单元,参数2为纹理坐标数组
OSG中使用texture类
来表示和处理纹理,其中的类方法如下:
上面S,T,R代表X,Y,Z轴。
texture类
的派生类Texture2D类
(常用):
二维纹理(Texture2D)要求图像的宽度和高度必须是2的幂次方。
OSG用Texture1D类
来表示和处理一维纹理,类方法Texture1D::setTextureWidth(int ) 用来表示一维纹理的宽度
例程代码:
void createTexture2D(osg::StateSet& ss) //ss为一个StateSet实例
{
osg::ref_ptr<osg::Texture2D>texture = new osg::Texture2D;
//用于存放二维纹理
texture->setImage(osgDB::readImageFile("clockface"));
//将图片存入
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
//设置纹理滤波方式
texture->setWrap(osg::Texture::WRAP_S,
osg::Texture::CLAMP_TO_BORDER);
texture->setWrap(osg::Texture::WRAP_T,
osg::Texture::CLAMP_TO_BORDER);
//设置纹理边界截取方式,osg::Texture::REPEAT为重复纹理绘制
texture->setBorderColor(osg::Vec4(1.0,1.0,0.0,1.0));
//设置纹理边框颜色
ss.setTextureAttributeAndModes(0,texture.get());
//关联其纹理并许可对应模式
}
渲染状态也可以进行回调,与节点回调类似。
fog->setStart(1.0);
和fog->setEnd(2000.0);
函数用于设置雾的起始距离和终止距离。