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

前后对比

使用前使用后
imageimage

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

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在OpenSceneGraph中,可以使用`osg::Camera`类将场景渲染到纹理上,然后再将纹理绘制到图片上。以下是将一个几何体渲染到图片上的示例代码: ``` // 创建几何体 osg::ref_ptr<osg::Geometry> geom = createGeometry(); // 创建摄像机 osg::ref_ptr<osg::Camera> camera = new osg::Camera; camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f)); camera->setViewport(0, 0, width, height); camera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height)); camera->setRenderOrder(osg::Camera::PRE_RENDER); camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); // 创建纹理 osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D; texture->setTextureSize(width, height); texture->setInternalFormat(GL_RGBA); texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); // 将纹理设置为摄像机的颜色缓冲区 camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); // 创建场景图 osg::ref_ptr<osg::Group> root = new osg::Group; root->addChild(geom); root->addChild(camera); // 渲染场景 osgViewer::Viewer viewer; viewer.setSceneData(root); viewer.setCameraManipulator(new osgGA::TrackballManipulator); viewer.realize(); viewer.frame(); // 将纹理绘制到图片上 osg::ref_ptr<osgDB::ReaderWriter::Options> options = new osgDB::ReaderWriter::Options; options->setOptionString("writeImageHint=png"); osgDB::writeImageFile(*texture->getImage(0), "output.png", options.get()); ``` 在上述代码中,首先创建了一个几何体`geom`。然后,创建了一个摄像机`camera`,并设置其视口、投影矩阵、渲染顺序和渲染目标等属性。接着,创建了一个纹理`texture`,设置其大小、内部格式和过滤器等属性,并将其设置为摄像机的颜色缓冲区。接下来,创建了一个场景图`root`,将几何体和摄像机添加到场景图中。通过`osgViewer::Viewer`类渲染场景,并将纹理绘制到图片上。最后,使用`osgDB::writeImageFile()`方法将纹理保存到图片文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值