5、osg绘制正方形和四方块以及内置的几何图形

本文详细介绍了如何使用OpenSceneGraph库创建一个几何图形,包括定义坐标、颜色和法线,以及设置几何体的关联方式和绘制效果。通过代码示例展示了如何创建正方形、四方块和其他几何形状,并调整线框宽度。

1、首先要定义一个几何图形,用来创建正方形的一个对象,这个对象根据坐标,颜色来进行绘制,如下代码创建一个几何对象:

osg::ref_ptr<osg::Geometry> geom=new osg::Geometry();//定义一个几何体
2、创建一个坐标集合对象,并且向对象中存入4个3维坐标点,如下代码所示:

//首先定义四个点
osg::ref_ptr<osg::Vec3Array> v=new osg::Vec3Array();//定义一个几何体坐标集合
v->push_back(osg::Vec3(-1.0,0.0,-1.0));//左下角坐标点
v->push_back(osg::Vec3(1.0,0.0,-1.0));//右下角坐标点
v->push_back(osg::Vec3(1.0,0.0,1.0));//右上角坐标点
v->push_back(osg::Vec3(-1.0,0.0,1.0));//左上角坐标点
geom->setVertexArray(v.get());//将坐标设置到几何体节点中

以下是坐标解释,在osg中,左右是x轴(左负,右正),上下为z轴(上正,下负),里外是y轴(里正,外负),如下图所示:


那么根据坐标可在图中画出图形,如下图所示:



3、创建一个颜色集合数组,分别向该集合存入四个颜色,每个颜色代表一个顶点,一共四种颜色,并且通过setColorArray与原来的几何体进行关联,并设置颜色绑定方式为逐点绑定,如下代码所示:

//定义颜色数组
osg::ref_ptr<osg::Vec4Array> c=new osg::Vec4Array();//定义一个颜色数组颜色
c->push_back(osg::Vec4(1.0,0.0,0.0,1.0));//数组的四个参数分别为RGBA,其中A表示透明度
c->push_back(osg::Vec4(0.0,1.0,0.0,1.0));
c->push_back(osg::Vec4(0.0,0.0,1.0,1.0));
c->push_back(osg::Vec4(1.0,1.0,1.0,1.0));
geom->setColorArray(c.get());//与几何体中进行关联
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);//设置绑定方式为逐点绑定。
4、定义图形的法线,就是我们从哪个方向去看图形,先定义一个坐标集合,然后向集合中添加一个法线坐标,然后通过setNormalArray设置法线,并通过setNormalBinding来绑定法线,并设置顶点关联方式,如下代码所示:

//定义法线
osg::ref_ptr<osg::Vec3Array> n=new osg::Vec3Array();//定义了一个法线绑定到该四方体中
n->push_back(osg::Vec3(0.0,-1.0,0.0));//法线为指向Y轴负半轴
geom->setNormalArray(n.get());//添加法线到几何体中
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);//将法线进行绑定
//设置顶点的关联方式,这里是Quad方式,总共有这么些方式: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));
5、定义一个几何组,并把刚创建好的geom集合体添加到组中,如下代码所示:

//定义一个几何组结点,并把几何体结点加入到几何组结点当中
osg::ref_ptr<osg::Geode> geode=new osg::Geode();
geode->addDrawable(geom.get());
如下所有代码所示:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>//Geode是专门管理可绘制几何体的总闸
#include <osg/Geometry>
osg::ref_ptr<osg::Node> createQuade();
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::ref_ptr<osg::Group> root=new osg::Group();
	root->addChild(createQuade().get());
	viewer.setSceneData(root.get());
	viewer.realize();
	return viewer.run();
}
osg::ref_ptr<osg::Node> createQuade()
{
	osg::ref_ptr<osg::Geometry> geom=new osg::Geometry();//定义一个几何体
	//首先定义四个点
	osg::ref_ptr<osg::Vec3Array> v=new osg::Vec3Array();//定义一个几何体坐标集合
	v->push_back(osg::Vec3(-1.0,0.0,-1.0));//左下角坐标点
	v->push_back(osg::Vec3(1.0,0.0,-1.0));//右下角坐标点
	v->push_back(osg::Vec3(1.0,0.0,1.0));//右上角坐标点
	v->push_back(osg::Vec3(-1.0,0.0,1.0));//左上角坐标点
	geom->setVertexArray(v.get());//将坐标设置到几何体节点中
	//定义颜色数组
	osg::ref_ptr<osg::Vec4Array> c=new osg::Vec4Array();//定义一个颜色数组颜色
	c->push_back(osg::Vec4(1.0,0.0,0.0,1.0));//数组的四个参数分别为RGBA,其中A表示透明度
	c->push_back(osg::Vec4(0.0,1.0,0.0,1.0));
	c->push_back(osg::Vec4(0.0,0.0,1.0,1.0));
	c->push_back(osg::Vec4(1.0,1.0,1.0,1.0));
	geom->setColorArray(c.get());//与几何体中进行关联
	geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);//设置绑定方式为逐点绑定。
	//定义法线
	osg::ref_ptr<osg::Vec3Array> n=new osg::Vec3Array();//定义了一个法线绑定到该四方体中
	n->push_back(osg::Vec3(0.0,-1.0,0.0));//法线为指向Y轴负半轴
	geom->setNormalArray(n.get());//添加法线到几何体中
	geom->setNormalBinding(osg::Geometry::BIND_OVERALL);//将法线进行绑定
	//设置顶点的关联方式,这里是Quad方式,总共有这么些方式: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();
}
其运行效果如下图所示:

正面


反面
6、如果要绘制四方块,则只需要更改一个参数即可,将geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));中的QUADS更改为LINE_LOOP即可,参数可以为:POINTS[点],LINES[线],LINE_STRIP[线带],LINE_LOOP[闭合线段],TRIANGLES[三角形],TRIANGLE_STRIP[三角带],TRIANGLE_FAN[三角扇],QUADS[四方块],QUAD_STRIP[四方块带],POLYGON[多边形],更改之后的效果如下所示:

7、设置线框的宽度,需要添加一个LineWidth对象,如下代码所示:
osg::ref_ptr<osg::LineWidth> lineSize=new osg::LineWidth();
lineSize->setWidth(10.0);//设置线的宽度
geom->getOrCreateStateSet()->setAttributeAndModes(lineSize.get(),osg::StateAttribute::ON);
8、整个代码如下所示:
#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>//Geode是专门管理可绘制几何体的总闸
#include <osg/Geometry>
#include <osg/LineWidth>
osg::ref_ptr<osg::Node> createQuade();
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::ref_ptr<osg::Group> root=new osg::Group();
	root->addChild(createQuade().get());
	viewer.setSceneData(root.get());
	viewer.realize();
	return viewer.run();
}
osg::ref_ptr<osg::Node> createQuade()
{
	osg::ref_ptr<osg::Geometry> geom=new osg::Geometry();//定义一个几何体
	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();//定义一个几何体坐标集合
	v->push_back(osg::Vec3(-1.0,0.0,-1.0));//左下角坐标点
	v->push_back(osg::Vec3(1.0,0.0,-1.0));//右下角坐标点
	v->push_back(osg::Vec3(1.0,0.0,1.0));//右上角坐标点
	v->push_back(osg::Vec3(-1.0,0.0,1.0));//左上角坐标点
	geom->setVertexArray(v.get());//将坐标设置到几何体节点中
	//定义颜色数组
	osg::ref_ptr<osg::Vec4Array> c=new osg::Vec4Array();//定义一个颜色数组颜色
	c->push_back(osg::Vec4(1.0,0.0,0.0,1.0));//数组的四个参数分别为RGBA,其中A表示透明度
	c->push_back(osg::Vec4(0.0,1.0,0.0,1.0));
	c->push_back(osg::Vec4(0.0,0.0,1.0,1.0));
	c->push_back(osg::Vec4(1.0,1.0,1.0,1.0));
	geom->setColorArray(c.get());//与几何体中进行关联
	geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);//设置绑定方式为逐点绑定。
	//定义法线
	osg::ref_ptr<osg::Vec3Array> n=new osg::Vec3Array();//定义了一个法线绑定到该四方体中
	n->push_back(osg::Vec3(0.0,-1.0,0.0));//法线为指向Y轴负半轴
	geom->setNormalArray(n.get());//添加法线到几何体中
	geom->setNormalBinding(osg::Geometry::BIND_OVERALL);//将法线进行绑定
	//设置顶点的关联方式,这里是Quad方式,总共有这么些方式:POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,TRIANGLE_STRIP,TRIANGLE_FAN,QUADS,QUAD_STRIP,POLYGON
	//此关联方式来决定绘制什么样的图形,比如Quad表示四方块,POINTS[点],LINES[线],LINE_STRIP[线带],LINE_LOOP[闭合线段],TRIANGLES[三角形],TRIANGLE_STRIP[三角带],TRIANGLE_FAN[三角扇],QUADS[四方块],QUAD_STRIP[四方块带],POLYGON[多边形]
	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();
}
运行效果如下所示:
8、在osg中的几何类型都包含在osg::Shape类中,然后将这些在添加到geode中,最后将geode添加到root中进行渲染,其形状可以分为:osg::Box[盒子],osg::Capsule[胶囊形],osg::CompositeShape[组合型],osg::Cone[圆锥形],osg::Cylinder[圆柱形],osg::HeightField[高程形],osg::InfinitePlane[有限面],osg::Sphere[球形],osg::TriangleMesh[三角蒙皮]。
如以下代码:
#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>//Geode是专门管理可绘制几何体的总闸
#include <osg/Geometry>
#include <osg/ShapeDrawable>
#include <osg/Shape>
osg::ref_ptr<osg::Node> createShape();
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::ref_ptr<osg::Group> root=new osg::Group();
	root->addChild(createShape().get());
	viewer.setSceneData(root.get());
	viewer.realize();
	return viewer.run();
}
osg::ref_ptr<osg::Node> createShape()
{
	osg::ref_ptr<osg::Geode> geode=new osg::Geode();
	float radius=0.08;//(以米为单位)
	float height=0.1;
	osg::TessellationHints *hints=new osg::TessellationHints();
	hints->setDetailRatio(0.5);//表示模型的粗细度。值越大精细度就越大。打个比方,当精细度小时,一个球可能只有几条线组成,很不圆。但是当精细度大时就十分像个球了。
	//绘制一个球型,以(0,0,0)为圆心,以0.08为半径,精细度为hints绘制一个球体
	geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0,0.0,0.0),radius),hints));
	//以(0.2,0,0)为坐标,以0.16为盒心,以长0.16米为长,绘制一个立方体
	geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.2,0.0,0.0),2*radius),hints));
	//以底面圆心(0.2,0,0)为坐标,半径为0.08米为圆心,以0.1米为高度,绘制一个圆锥
	geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.4,0.0,0.0),radius,height),hints));
	//以底面圆心(0.6,0,0)为坐标,半径为0.08米为圆心,以0.1米为高度,绘制一个圆柱体
	geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.6,0.0,0.0),radius,height),hints));
	//以圆心(0.8,0,0)为坐标,半径为0.08米为圆心,以0.1米为高度,绘制一个胶囊体
	geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(0.8,0.0,0.0),radius,height),hints));
	return geode.get();
}
运行效果如下:


<think>好的,用户想要了解osgeEarth如何绘制几何图形。首先,我需要回忆一下osgeEarth的基本知识。osgeEarth是基于OSG的三维地球渲染引擎,主要用于地理信息的可视化。绘制几何图形应该涉及到如何创建显示点、线、面等基本要素。 用户可能对osgeEarth不太熟悉,所以需要从基础开始介绍。首先,应该提到osgeEarth是构建在OpenSceneGraph之上的,因此它继承了OSG的节点场景图结构。接着,绘制几何图形通常需要创建几何体对象,设置顶点、颜色等属性,然后添加到场景中。 接下来,分步骤说明如何绘制不同的几何图形。比如点、线、多边形,每个部分需要示例代码,但用户可能更关注的是逻辑步骤而不是完整的代码。需要注意代码的格式,用户提到行内数学表达式用$...$,但这里是代码,应该用代码,不过原问题中没有特别说明代码的格式,可能需要用Markdown的代码。 然后,可能需要提到坐标系的问题,因为在地球上绘制几何图形通常需要考虑地理坐标系,比如WGS84,或者投影坐标系。osgeEarth可能默认使用地理坐标,经度、纬度、高程,所以需要确保用户设置的坐标是正确的。 另外,osgeEarth可能有自己的图层节点结构,比如FeatureNode或者AnnotationNode,用于高效地显示地理要素。是否需要使用这些高级功能?可能需要简要提及,但用户的问题可能更关注基础绘制方法。 还要注意性能优化,比如几何图形的简化、LOD(层次细节)等,但可能用户目前只需要基础功能,这部分可以作为扩展内容简要提到。 最后,是否需要给出一个完整的示例代码框架?用户可能希望看到具体的实现步骤,比如创建几何体、设置顶点、设置颜色、创建Geode节点,添加到场景根节点等。同时,提醒用户注意坐标系的转换,比如在osgEarth中可能需要使用GeoTransform来正确放置地理坐标下的几何体。 总结步骤: 1. 引入必要的头文件。 2. 创建几何体对象(如osg::Geometry)。 3. 设置顶点数组,添加顶点数据(包括坐标)。 4. 设置颜色、法线等属性。 5. 添加图元(如点、线、多边形)。 6. 创建Geode节点并将几何体添加到其中。 7. 将Geode节点添加到场景图中。 8. 对于地理坐标,可能需要使用GeoTransform节点来处理位置。 需要检查这些步骤是否正确,是否有遗漏。例如,在osgEarth中,直接使用OSG的Geode可能不会自动处理地球曲率,所以可能需要使用osgEarth提供的特定节点或方法,比如FeatureNode或者将几何体放置在正确的空间参考系下。 可能还需要提到如何设置样式,比如线宽、颜色、点的图标等,这些在osgEarth中可能有不同的处理方式,比如使用样式表或者特定的渲染属性。 需要确保回答结构清晰,分点说明,每个步骤有代码示例(如果有的话),并解释关键点。同时,提醒用户注意坐标系转换性能方面的考虑。</think>osgeEarth是基于OpenSceneGraph(OSG)的地理可视化引擎,用于在三维地球场景中绘制渲染地理数据。以下是绘制几何图形的分步指南: --- ### **1. 基本概念** - **几何图形类型**:点(Point)、线(Line)、面(Polygon)、文本标签等。 - **坐标系**:默认使用WGS84地理坐标系(经度、纬度、高程),需确保顶点数据符合此格式。 --- ### **2. 核心步骤** #### **(1) 创建几何对象** 使用OSG的`osg::Geometry`类定义几何图形: ```cpp osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; ``` #### **(2) 设置顶点数据** 定义顶点数组并绑定到几何体: ```cpp osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; vertices->push_back(osg::Vec3d(经度, 纬度, 高程)); // 添加顶点 geom->setVertexArray(vertices); ``` #### **(3) 定义图元类型** - **点**: ```cpp geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, vertices->size())); ``` - **线**: ```cpp geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, vertices->size())); ``` - **多边形**: ```cpp geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, vertices->size())); ``` #### **(4) 设置颜色与样式** ```cpp osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; colors->push_back(osg::Vec4(1.0, 0.0, 0.0, 1.0)); // RGBA红色 geom->setColorArray(colors); geom->setColorBinding(osg::Geometry::BIND_OVERALL); ``` #### **(5) 添加到场景图** ```cpp osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable(geom); viewer->setSceneData(geode); ``` --- ### **3. osgEarth优化方式** #### **(1) 使用GeoTransform定位** 将几何体放置到地球表面: ```cpp #include <osgEarth/GeoTransform> osg::ref_ptr<osgEarth::GeoTransform> geoTransform = new osgEarth::GeoTransform(); geoTransform->setPosition(osgEarth::GeoPoint(osgEarth::SpatialReference::get("wgs84"), 经度, 纬度, 高程)); geoTransform->addChild(geode); ``` #### **(2) 样式化(Style)** 通过`FeatureModel`定义高级样式(线宽、填充色等): ```cpp #include <osgEarth/FeatureModel> osgEarth::Style style; style.getOrCreate<osgEarth::LineSymbol>()->stroke()->color() = osgEarth::Color::Red; style.getOrCreate<osgEarth::LineSymbol>()->stroke()->width() = 2.0f; osgEarth::Feature* feature = new osgEarth::Feature(new osgEarth::LineString(坐标列表), nullptr, style); osgEarth::FeatureNode* featureNode = new osgEarth::FeatureNode(feature); viewer->getSceneManager()->getRoot()->addChild(featureNode); ``` --- ### **4. 注意事项** - **性能优化**:复杂图形建议使用批次处理(`osg::DrawArrays`)层级细节(LOD)。 - **坐标转换**:非WGS84数据需通过`osgEarth::SpatialReference`转换。 - **交互支持**:结合`osgEarth::AnnotationNode`实现点击事件与标签。 --- 通过上述步骤,您可以在osgEarth中高效绘制各类几何图形,并通过样式坐标系统配置实现精准的地理可视化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值