osgearth相控阵雷达

一、前言

         实现思路:先绘制半个圆,再添加四个裁剪面,这么拼凑一下就感觉有那么点意思呢:)。

二、效果

三、关键代码

void EffectPhasedArrayRadar::RebuildEntityBody()
{
	if (m_pGeode.valid()) {
		mat->removeChild(m_pGeode.get());
		m_pGeode = nullptr;
	}

	if (m_pGridCopy.valid()) {
		mat->removeChild(m_pGridCopy.get());
		m_pGridCopy = nullptr;
	}

	if (m_pPatch1.valid()) {
		mat->removeChild(m_pPatch1.get());
		m_pPatch1 = nullptr;
	}

	if (m_pPatch2.valid()) {
		mat->removeChild(m_pPatch2.get());
		m_pPatch2 = nullptr;
	}

	if (m_pPatch3.valid()) {
		mat->removeChild(m_pPatch3.get());
		m_pPatch3 = nullptr;
	}

	if (m_pPatch4.valid()) {
		mat->removeChild(m_pPatch4.get());
		m_pPatch4 = nullptr;
	}

	if (m_pClippedSubgraph.valid()) {
		mat->removeChild(m_pClippedSubgraph.get());
		m_pClippedSubgraph = nullptr;
	}

	if (m_pFanMT.valid()) {
		mat->removeChild(m_pFanMT.get());
		m_pFanMT = nullptr;
	}

	

	m_pGeode = new Geode();

	//设置三维曲面采样步长
	constexpr double dStep = 11.25;

	//垂直方向循环
	for (double vAngle = 0; vAngle <= 60; vAngle += dStep)
	{
		//三维曲面的半透明蒙皮,通过QUAD_STRIP图元合成
		m_polySkin = new Geometry();
		//计算蒙皮所需要的采样点数量
		constexpr int numCoordsSkin = (360 / dStep + 1) * 2;//146
															//申请蒙皮采样点
		Vec3 myCoordsSkin[numCoordsSkin];// = new Vec3[numCoordsSkin];

		osg::ref_ptr<Vec4Array> colorsSkin = new Vec4Array;
		osg::ref_ptr<Vec3Array> normals = new Vec3Array;
		normals->push_back(Vec3(0.0f, -1.0f, 0.0f));
		int index = 0;
		//水平方向循环
		for (double hAngle = 0; hAngle <= 360; hAngle += dStep)
		{
			double vAngleR = DegreesToRadians(vAngle);
			double hAngleR = DegreesToRadians(hAngle);
			double vAngleNextStepR = DegreesToRadians(vAngle + dStep);

			//计算蒙皮的采样点坐标,同时计算对应的显示颜色
			//圈上的点
			myCoordsSkin[index] = Vec3(
				m_dRadius  *sin(vAngleR)*cos(hAngleR),
				m_dRadius  *sin(vAngleR)* sin(hAngleR),
				m_dRadius * cos(vAngleR));
			//圈上方点
			myCoordsSkin[index + 1] = Vec3(
				m_dRadius *sin(vAngleNextStepR)  *  cos(hAngleR),
				m_dRadius *sin(vAngleNextStepR)  *  sin(hAngleR),
				m_dRadius * cos(vAngleNextStepR));

			colorsSkin->push_back(Vec4(0.0,1.0,1.0, m_dColorAlpha));
			colorsSkin->push_back(Vec4(0.0, 1.0, 1.0, m_dColorAlpha));

			index += 2;
		}
		m_verticesSkin = new Vec3Array(numCoordsSkin, myCoordsSkin);
		m_polySkin->setVertexArray(m_verticesSkin);
		//设置曲面的颜色为逐点设置
		m_polySkin->setColorArray(colorsSkin.get(), Array::BIND_PER_VERTEX);
		//m_polySkin->setNormalArray(normals, Array::BIND_OVERALL);
		//设置曲面的图元类型为QUAD_STRIP
		m_polySkin->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUAD_STRIP, 0, numCoordsSkin));//QUAD_STRIP为四边形,三角面数相同
																									//设置曲面半透明效果的一条关键语句,少了该句会导致半透明显示错误,暂未搞清楚该句的原理
		m_polySkin->getOrCreateStateSet()->setAttribute(new Depth(Depth::LESS, 0.0, 1.0, false));
		//开启曲面的半透明效果
		m_polySkin->getOrCreateStateSet()->setMode(GL_BLEND, StateAttribute::ON);
		m_polySkin->getOrCreateStateSet()->setRenderingHint(StateSet::TRANSPARENT_BIN);
		m_polySkin->getOrCreateStateSet()->setMode(GL_LIGHTING, StateAttribute::OFF);
		//背面剔除
		m_polySkin->getOrCreateStateSet()->setMode(GL_CULL_FACE, StateAttribute::OFF);
		//smooth geoset by creating per vertex normals.
		osgUtil::SmoothingVisitor::smooth(*m_polySkin.get());
		m_pGeode->addDrawable(m_polySkin);
	}

	//绘制网格线
	m_pGridCopy = dynamic_cast<Geode *>(m_pGeode->clone(CopyOp::DEEP_COPY_ALL));
	ref_ptr<StateSet> spStateSet = m_pGridCopy->getOrCreateStateSet();
	ref_ptr<PolygonMode> polyMode = new PolygonMode(PolygonMode::FRONT_AND_BACK, PolygonMode::LINE);
	spStateSet->setAttribute(polyMode);

	// 设置线框颜色
	osg::ref_ptr<osg::Material> material = new osg::Material();
	material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 1, 1, 1));
	material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 1, 1, 1));
	spStateSet->setAttributeAndModes(material, osg::StateAttribute::ON);

	// 启用多边形偏移解决Z-fighting
	ref_ptr<PolygonOffset> polyOffset = new PolygonOffset;
	polyOffset->setFactor(-1.0f);
	polyOffset->setUnits(-1.0f);
	spStateSet->setAttributeAndModes(polyOffset, StateAttribute::ON);

	// 关闭透明混合
	spStateSet->setMode(GL_BLEND, StateAttribute::OFF);
	spStateSet->setRenderingHint(StateSet::OPAQUE_BIN);

	// 确保深度测试正确
	spStateSet->setMode(GL_DEPTH_TEST, StateAttribute::ON);
	spStateSet->setMode(GL_LIGHTING, StateAttribute::OFF);

	ref_ptr<LineWidth> lineWidth = new LineWidth(1.0f);
	spStateSet->setAttribute(lineWidth);

	// 创建裁剪节点和裁剪平面
	osg::ref_ptr<osg::ClipPlane> clipPlane1 = new osg::ClipPlane(0, osg::Vec4d(0, 0.707, 0.707, 0.0));
	osg::ref_ptr<osg::ClipPlane> clipPlane2 = new osg::ClipPlane(1, osg::Vec4d(0, -0.707, 0.707, 0.0));
	osg::ref_ptr<osg::ClipPlane> clipPlane3 = new osg::ClipPlane(2, osg::Vec4d(0.707, 0, 0.707, 0.0));
	osg::ref_ptr<osg::ClipPlane> clipPlane4 = new osg::ClipPlane(3, osg::Vec4d(-0.707, 0, 0.707, 0.0));

	m_pClippedSubgraph = new osg::Group;
	osg::ref_ptr<osg::StateSet> stateset = m_pClippedSubgraph->getOrCreateStateSet();
	//添加裁剪面
	stateset->setAttributeAndModes(clipPlane1, osg::StateAttribute::ON);
	stateset->setAttributeAndModes(clipPlane2, osg::StateAttribute::ON);
	stateset->setAttributeAndModes(clipPlane3, osg::StateAttribute::ON);
	stateset->setAttributeAndModes(clipPlane4, osg::StateAttribute::ON);
	//stateset->setMode(GL_CLIP_PLANE0, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
	//stateset->setMode(GL_CLIP_PLANE1, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
	//stateset->setMode(GL_CLIP_PLANE2, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
	//stateset->setMode(GL_CLIP_PLANE3, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

	// 被裁剪的部分(原半球)
	m_pClippedSubgraph->addChild(m_pGeode.get());
	m_pClippedSubgraph->addChild(m_pGridCopy.get());

	/*
		创建补全的四个面,y朝下x朝右
		如果将四个补面和扇子添加到m_pClippedSubgraph里面就更完美,但不知道为什么,添加进去就会闪烁
		有时间了再演技。
	*/

	//+x轴方向的补面
	m_pPatch1 = CreatePatch(-45.0, osg::Vec3d(0, 1, 0), 45.0, -45.0);
	mat->addChild(m_pPatch1.get());
	//-y轴方向的补面
	m_pPatch2 = CreatePatch(45.0, osg::Vec3d(1, 0, 0), 135.0, 45.0);
	mat->addChild(m_pPatch2.get());
	//-x轴方向补面
	m_pPatch3 = CreatePatch(45.0, osg::Vec3d(0, 1, 0), 225.0, 135.0);
	mat->addChild(m_pPatch3.get());
	//+y轴方向补面
	m_pPatch4 = CreatePatch(-45.0, osg::Vec3d(1, 0, 0), 315.0, 225.0);
	mat->addChild(m_pPatch4.get());

	//中间的扇子
	m_pFanMT = new osg::MatrixTransform();
	m_pFanMT->addChild(CreateSector(135, 45, 0.5).get());

	mat->addChild(m_pFanMT.get());
	mat->addChild(m_pClippedSubgraph.get());
}

原创不易,记得点赞加关注哦,我会持续分享实用的功能(:-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一梦、んんん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值