OSG 之学习三:OSG 基本几何图元

该博客是 OSG 入门内容,示例源于《OSG 程序设计教程》。介绍了基本绘制方法,包括绘制正方形、所有可绘制图元(如点、线、三角形等)及设置线宽属性,还列举了九种内置几何类型,如盒子、球形等,最后提及一些类参考需自行查看。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明


  • 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();
}

在这里插入图片描述

2. 一些类参考,自己看之


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值