OSG 绘制Geometry使用

OSG的几何绘制

osg 绘制使用的OpenGL的绘制过程
image

1. OSG绘制简单线

使用简单线绘制,使用OpenGL的绘制的线的能力过程

		// create Geometry object to store all the vertices and lines primitive.
		osg::Geometry* linesGeom = new osg::Geometry();
		//创建定点数据
		osg::Vec3Array* vertices = new osg::Vec3Array(8);
		(*vertices)[0].set(-1.13704, -2.15188e-09, 0.40373);
		(*vertices)[1].set(-0.856897, -2.15188e-09, 0.531441);
		(*vertices)[2].set(-0.889855, -2.15188e-09, 0.444927);
		(*vertices)[3].set(-0.568518, -2.15188e-09, 0.40373);
		(*vertices)[4].set(-1.00933, -2.15188e-09, 0.370773);
		(*vertices)[5].set(-0.716827, -2.15188e-09, 0.292498);
		(*vertices)[6].set(-1.07936, 9.18133e-09, 0.317217);
		(*vertices)[7].set(-0.700348, 9.18133e-09, 0.362533);
		
		
		// 设置到定点数组
		linesGeom->setVertexArray(vertices);

		// set the colors as before, plus using the above
		osg::Vec4Array* colors = new osg::Vec4Array;
		colors->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
		linesGeom->setColorArray(colors, osg::Array::BIND_OVERALL);

		//设置线宽
		osg::LineWidth* linew = new osg::LineWidth(4);
		linesGeom->getOrCreateStateSet()->setAttributeAndModes(linew);

		// 对应上图绘制线的参数
		linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 8));

		// add the points geometry to the geode.
		geode->addDrawable(linesGeom);

2. osg 绘制简单面

		osg::Geometry* linesGeom = new osg::Geometry();
		//创建定点数据
		osg::Vec3Array* vertices = new osg::Vec3Array(8);
		(*vertices)[0].set(-1.13704, -2.15188e-09, 0.40373);
		(*vertices)[1].set(-0.856897, -2.15188e-09, 0.531441);
		(*vertices)[2].set(-0.889855, -2.15188e-09, 0.444927);
		(*vertices)[3].set(-0.568518, -2.15188e-09, 0.40373);
		(*vertices)[4].set(-1.00933, -2.15188e-09, 0.370773);
		(*vertices)[5].set(-0.716827, -2.15188e-09, 0.292498);
		(*vertices)[6].set(-1.07936, 9.18133e-09, 0.317217);
		(*vertices)[7].set(-0.700348, 9.18133e-09, 0.362533);


		// 设置到定点数组
		linesGeom->setVertexArray(vertices);

		// set the colors as before, plus using the above
		osg::Vec4Array* colors = new osg::Vec4Array;
		colors->push_back(osg::Vec4(1.0f, 0.0f, 0.5f, 0.5f));
		linesGeom->setColorArray(colors, osg::Array::BIND_OVERALL);


		// This time we simply use primitive, and hardwire the number of coords to use
		// since we know up front,
		linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, 8));

		// add the points geometry to the geode.
		geode->addDrawable(linesGeom);

说明不规则多边形绘会出现一些问题,osg中解决两种解决办法

  1. 自己三角化多边形,网上可以搜索一些算法
  2. 使用osg::Tessellator
  • 关键代码
		osg::ref_ptr<osgUtil::Tessellator> tscx = new osgUtil::Tessellator();
		tscx->setTessellationNormal(osg::Vec3(0.0, -1.0, 0));//面的法线向量
		tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
		tscx->setBoundaryOnly(false);
		tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD); // the commonest tessellation is default, ODD. GE2 allows intersections of constraints to be found.
		tscx->retessellatePolygons(*(linesGeom)); // this should insert extra vertices where constraints overlap

前后对比

使用前 使用后
image image

3. 使用纹理绘制多边形

主要能解决绘制带符号样式的面,不仅仅是简单颜色填充的面。

用到了OpenGL纹理填充的知识
参照

	osg::Geometry* linesGeom = new osg::Geometry();
		//创建定点数据
		osg::Vec3Array* vertices = new osg::Vec3Array(8);
		(*vertices)[0].set(-1.13704, -2.15188e-09, 0.40373);
		(*vertices)[1].set(-0.856897, -2.15188e-09, 0.531441);
		(*vertices)[2].set(-0.889855, -2.15188e-09, 0.444927);
		(*vertices)[3].set(-0.568518, -2.15188e-09, 0.40373);
		(*vertices)[4].set(-1.00933, -2.15188e-09, 0.370773);
		(*vertices)[5].set(-0.716827, -2.15188e-09, 0.292498);
		(*vertices)[6].set(-1.07936, 9.18133e-09, 0.317217);
		(*vertices)[7].set(-0.700348, 9.18133e-09, 0.362533);

		// 设置到定点数组
		linesGeom->setVertexArray(vertices);

		// set the colors as before, plus using the above
		osg::Vec4Array* colors = new osg::Vec4Array;
		colors->push_back(osg::Vec4(1.0f, 0.0f, 0.5f, 0.5f));
		linesGeom->setColorArray(colors, osg::Array::BIND_OVERALL);
		//
		osg::Vec3Array* normals = new osg::Vec3Array;
		normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
		linesGeom->setNormalArray(normals, osg::Array::BIND_OVERALL);
		//设置线宽

		// This time we simply use primitive, and hardwire the number of coords to use
		// since we know up front,
		linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, 8));
		//贴图纹理
		osg::Texture2D* texture = new osg::Texture2D;
		texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::WrapMode::REPEAT);//贴图填充的方式
		texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::WrapMode::REPEAT);//贴图填充的方式
		texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
		texture->setImage(osgDB::readRefImageFile("a-duijiangji_select.png"));

		osg::StateSet* stateset = linesGeom->getOrCreateStateSet();
		stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
		//
		stateset->setMode(GL_BLEND, osg::StateAttribute::ON);//开启透明
		stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);//关闭深度测试
		osg::BlendFunc * aphlafunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		stateset->setAttribute(aphlafunc, osg::StateAttribute::ON);
		osg::Program* program = new osg::Program;
		program->setName("microshader");
		//shader

		 const char *microshaderVertSource = {
			"// microshader - colors a fragment based on its position\n"
			"varying vec2 m_tex;\n"
			"void main(void)\n"
			"{\n"
			 "    m_tex = vec2(gl_Vertex.x*20.0,gl_Vertex.z*20.0);\n"//面纹理的主要方法
			"    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
			"}\n"
		};

		 const char *microshaderFragSource = {
			"varying vec2 m_tex;\n"
			"uniform sampler2D baseTexture;                                          \n"
			"void main(void)\n"
			"{\n"
			"    gl_FragColor = texture2D( baseTexture, m_tex );\n"
			"}\n"
		};

		program->addShader(new osg::Shader(osg::Shader::VERTEX, microshaderVertSource));
		program->addShader(new osg::Shader(osg::Shader::FRAGMENT, microshaderFragSource));
		stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
		// add the points geometry to the geode.
		geode->addDrawable(linesGeom);
		//
		osg::ref_ptr<osgUtil::Tessellator> tscx = new osgUtil::Tessellator();
		tscx->setTessellationNormal(osg::Vec3(0.0, -1.0, 0));//面的法线向量
		tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
		tscx->setBoundaryOnly(false);
		tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD); // the commonest tessellation is default, ODD. GE2 allows intersections of constraints to be found.
		tscx->retessellatePolygons(*(linesGeom)); // this should insert extra vertices where constraints overlap

绘制效果

image

4. 实际案例分析

现在有一下需求,在椎体上绘制的,并投影到地面的效果,如下图

image

分析需要一下技术点:

  • osg的OverlayNode的类,
  • 椎体的定点和纹理坐标的对应生成
  1. overlayNode的关键代码
 osgSim::OverlayNode* overlayNode = new osgSim::OverlayNode(technique);
        /*每一帧都更新overlay的纹理*/
        overlayNode->setContinuousUpdate(true);
        /*设置将渲染成纹理的节点*/
        overlayNode->setOverlaySubgraph(movingModel);
        /*设置映射的高度,设成比地面低一点即可*/
        overlayNode->setOverlayBaseHeight(baseHeight-0.01);
        overlayNode->addChild(baseModel);//地面节点
  1. 椎体以及纹理关键代码
	
osg::Node* CreateZhuiti(const osg::Vec3& center, float radius, float angle)
{
	float r2 = std::sin(osg::DegreesToRadians(angle))*radius;
	float z = std::cos(osg::DegreesToRadians(angle))*radius;
	int size = 50;
	osg::Vec3Array* vertices = new osg::Vec3Array();
	osg::Vec2Array* coords = new osg::Vec2Array();
	double step = osg::PI * 2 / size;
	for (int i = 0; i < size; i++)
	{
		float x = std::sin(i*step)*r2;
		float y = std::cos(i*step)*r2;
		vertices->push_back(osg::Vec3(x, y, z) + center);
		vertices->push_back(center);
		//纹理坐标
		coords->push_back(osg::Vec2( i*1.0 / size, 1));
		coords->push_back(osg::Vec2( i*1.0 / size, 0));
	}
	vertices->push_back((*vertices)[0]);
	coords->push_back(osg::Vec2(1, 1));
	//
	osg::Geometry* linesGeom = new osg::Geometry();

	// 设置到定点数组
	linesGeom->setVertexArray(vertices);
	linesGeom->setTexCoordArray(0, coords);

	// set the colors as before, plus using the above
	osg::Vec4Array* colors = new osg::Vec4Array;
	colors->push_back(osg::Vec4(1.0f, 1.0f, 1.f, 1.f));
	linesGeom->setColorArray(colors, osg::Array::BIND_OVERALL);
	//
	osg::Texture2D* texture = new osg::Texture2D;
	texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
	texture->setImage(osgDB::readRefImageFile("image12.jpg"));

	osg::StateSet* stateset = linesGeom->getOrCreateStateSet();
	stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
	//
	stateset->setMode(GL_BLEND, osg::StateAttribute::ON);//开启透明
														 // since we know up front,
	linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, vertices->size()));

	// add the points geometry to the geode.
	osg::Geode* geode = new osg::Geode;
	geode->addDrawable(linesGeom);
	return geode;
}

最终效果

image

版权声明:本文为Rsoftwaretest原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Rsoftwaretest/article/details/93033015

智能推荐

matplotlib 简单用法详解(转)

  show1:   show2: show3: show4: show5: show 6: show7: show8: show 9:...

沉淀再出发:spring boot的理解

沉淀再出发:spring boot的理解 一、前言     关于spring boot,我们肯定听过了很多遍了,其实最本质的东西就是COC(convention over configuration),将各种框架组装起来,省去了我们配置各种框架的时间,是一种更高层次的封装和抽象,正如maven整合了很多的jar包一样,spring boot整合了很多的框架和操作,我们...

注释(附彩蛋)、关键字、标识符、数据类型、类型转换、变量(重点)、常量

注释 注释相当于一种提示,系统识别不到,便于程序员以后修改时观看 单行注释 多行注释 文档注释 彩蛋:百度搜索:有趣的代码注释 即可get 关键字、标识符 Java所有的组成部分都需要名字.类名,变量名,方法名都被称标识符 所有的标识符只能以字母$_开头 不能使用关键字或保留字命名 数据类型 基本数据类型 引用数据类型 字符的本质是数字,字符可以通过强制转换成数字 转义字符:/t 制表符 /n换行...

微信小程序学习笔记(1) -- 基础知识入门

文章目录 微信小程序 一、简单了解 1.常用api 2.常用ui地址 二、微信小程序应用配置 根目录 app.json界面外观 pages window debug: app.js: wxss 页面结构 page.json 标签栏 三、逻辑层与界面层分离架构 逻辑层的JavaScript 演示: getApp 演示 getCurrentPages() 演示符合commonjs规范 演示 wx对象 ...

hive不能创建表

可以创建数据库,但是创建不了表: 本来我以为是mysql放在hive的lib下的jar包的问题,然后我换了一下jar包还是这样,经过多次尝试想到可能是这个原装的hive数据库的字符有问题。 这样我们就先退出hive,然后连接上linux里面的mysql数据库: 连接上mysql之后 连接上数据库,删除这个hive库 drop database hive; (分号别忘了) 然后在手动创建一个crea...

猜你喜欢

函数和递归

两个库函数 strcpy memset:Sets buffers to a specified character(将缓冲区设置为指定字符) 注: 但是库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件。 void 为无数据类型 不能直接定义一个数字 自定义函数 自定义函数和库函数一样,有函数名,返回值类型和函数参数。 但是不一样的是这些都是我们自己来设计。 写一个...

Spark GraphX图计算框架原理概述

言之易而为之难,学习大数据之图计算,就是从“浊”中找出“静”的规律,达到“清”的境界;从“安”中找出“生”的状态。 转发请标明原文地址:原文地址 概述 GraphX是Spark中用于图和图计算的组件,GraphX通过扩展Spark RDD引入了一个新的图抽象数据结构,一个将有效信...

博客作业05--查找

1.学习总结(2分) 1.1查找的思维导图 1.2 查找学习体会 查找有顺序查找,二分查找和分块查找。顺序查找的优点是算法简单,对表的结构无任何要求,但是查找效率低。二分查找是一种效率较高的方法,但是要将表按关键字排序,只适用顺序存储结构。哈希表的平均查找长度是α的函数,而不是n的函数,用哈希表构造查找表时,可以选择适当的装填因子α,使得平均查找长度在某个范围内。 2.PT...

Linux初学第七天<exec、system、和popen函数的用法>

一、exec 族函数        为什么叫族函数?因为 exec 有很多以exec 开头的函数:                    &...

剑指 Offer 14- II. 剪绳子 II

剑指 Offer 14- II. 剪绳子 II 链接:https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof/   剪绳子的思想跟https://blog.csdn.net/breeze_blows/article/details/107869399是一致的,只是这里涉及到大数,所以用到快速幂:https://zhuanlan.zhi...