说明
- OSG 入门看的,大佬绕道
- 示例来源于《OSG程序设计教程》
- 没有此电子书的小伙伴们,我已上传至CSDN
1. 基本绘制方法
1.1 绘制一个正方形
- 程序功能:绘制一个正方形
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode> // 专门管理可绘制几何体的总闸
#include <osg/Geometry> // 被管理的几何体
// 前向声明
osg::ref_ptr<osg::Node> createQuad(); // 返回的是 osg::Node 类型
void main() {
osgViewer::Viewer viewer;
osg::Group *root = new osg::Group();
root->addChild(createQuad().get()); // 绘制正方形的函数
viewer.setSceneData(root);
viewer.realize();
viewer.run();
}
osg::ref_ptr<osg::Node> createQuad() {
// 新建 osg::Geometry,申请了一个几何体结点
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// 首先定义四个点
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array; // osg::Vec3Array 申请了顶点序列
// 把顶点序列加入到几何体当中,最终所有的关连都在几何体当中
geom->setVertexArray(v.get()); // 这个是先 geom->setVertexArray,然后再 v->push_back
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)); // 依次存放顶点序列
v->push_back(osg::Vec3(-1.f, 0.f, 1.f)); // 依次存放顶点序列
// 定义颜色数组,申请颜色序列
osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array; // osg::Vec4Array
geom->setColorArray(c.get());
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); // 填充方式,设置绑定方式为逐点绑
c->push_back(osg::Vec4(1.f, 0.f, 0.f, 1.f)); // R
c->push_back(osg::Vec4(0.f, 1.f, 0.f, 1.f)); // G
c->push_back(osg::Vec4(0.f, 0.f, 1.f, 1.f)); // B
c->push_back(osg::Vec4(1.f, 1.f, 1.f, 1.f)); // A
// 定义法线
osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
geom->setNormalArray(n.get());
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
// 定义了一个法线绑定到该四方体中。法线为指向 Y 轴负半轴,
// 也就是说光从正上方往下照射;
// 法线不同会影响光照的效
n->push_back(osg::Vec3(0.f, -1.f, 0.f));
// 设置顶点关联方式,Primitive 原始的意思
// 总共有这么些方式:
// POINTS LINES LINE_STRIP LINE_LOOP
// TRIANGLES TRIANGLE_STRIP TRIANGLE_FAN
// QUADS QUAD_STRIP POLYGON
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
// 申请一个几何组结点,并把几何体结点加入到几何组结点当中
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(geom.get());
return geode.get();
}
1.2 所有可绘制图元
- POINTS[点]
- LINES[线]
- LINE_STRIP[线带]
- LINE_LOOP[闭合线段]
- TRIANGLES[三角形]
- TRIANGLE_STRIP[三角带]
- TRIANGLE_FAN[三角扇]
- QUADS[四方块]
- QUAD_STRIP[四方块带]
- POLYGON[多边形]
- else
在这里我们要以封闭的直线为例来说明如何设置线宽属性。所有的图元可能都有它的特殊性,但是大都与此种设置方法类似
- 程序功能:绘制线宽
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/LineWidth>
osg::ref_ptr<osg::Node> createLine();
void main() {
osgViewer::Viewer viewer;
osg::Group *root = new osg::Group();
root->addChild(createLine().get());
viewer.setSceneData(root);
viewer.realize();
viewer.run();
}
osg::ref_ptr<osg::Node> createLine() {
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// 限制线的宽度和改变图元
// 线宽是一种属性和状态,在 OSG 当中有专门的属性和状态类来管理这些
// 所有启动属性和状态的操作使用都与此类似
osg::ref_ptr <osg::LineWidth> LineSize = new osg::LineWidth;
LineSize->setWidth(10.0);
geom->getOrCreateStateSet()->setAttributeAndModes(LineSize.get(), osg::StateAttribute::ON);
// 首先定义四个点
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
geom->setVertexArray(v.get());
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));
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);
c->push_back(osg::Vec4(1.f, 0.f, 0.f, 1.f));
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);
n->push_back(osg::Vec3(0.f, -1.f, 0.f));
// 设置顶点关联方式
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 4));
// 几何组结点
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(geom.get());
return geode.get();
}
1.3 内置几何类型
形状共有九种,分别为
- osg::Box[盒子]
- osg::Capsule[胶囊形]
- osg::CompositeShape[组合型]
- osg::Cone[圆锥形]
- osg::Cylinder[圆柱形]
- osg::HeightField[高程形]
- osg::InfinitePlane[有限面]
- osg::Sphere[球形]
- osg::TriangleMesh[三角蒙皮]
- else
程序功能:绘制一些基本 shape
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/ShapeDrawable> // 新增头文件
#include <osg/Shape> // 新增头文件
osg::ref_ptr<osg::Node> createShape();
void main() {
osgViewer::Viewer viewer;
osg::Group *root = new osg::Group();
root->addChild(createShape().get());
viewer.setSceneData(root);
viewer.realize();
viewer.run();
}
osg::ref_ptr<osg::Node> createShape() {
// 几何组结点
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
// 申请两个变量表示几何体将要使用的半径与宽高等等
float radius = 0.08f;
float height = 0.1f;
// 表示模型的粗细度。值越大精细度就越大
// 打个比方,当精细度小时,一个球可能只有几条线组成,很不圆
// 但是当精细度大时就十分像个球
osg::TessellationHints *hints = new osg::TessellationHints;
hints->setDetailRatio(0.5f);
// 球结点:规定圆心、半径、精细度
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius), hints));
// 盒子结点:规定盒心、长、精细度
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.2f, 0.0f, 0.0f), 2 * radius), hints));
// 圆锥结点:规定底面圆心、半径、高度、精细度
geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.4f, 0.0f, 0.0f), radius, height), hints));
// 圆柱结点:规定底面圆心、半径、高度、精细度
geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.60f, 0.0f, 0.0f), radius, height), hints));
// 胶囊体结点:规定半径、圆心、高度、精细度
geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(0.80f, 0.0f, 0.0f), radius, height), hints));
return geode.get();
}