OsgEarth添加圆锥体

#pragma once
#include <osg/Node>
#include <osg/MatrixTransform>
#include "Pendant.h"

//三维实体的圆锥波束

class WaveBeamCone :public Pendant {
public:
	WaveBeamCone();
	~WaveBeamCone();

	void clearSelf()override;


	//创建圆锥形波束
	void createWaveBeamCone(osg::MatrixTransform* node,double angle, double length, osg::Vec4 color, osg::Vec4 lineColor, double lineWidth);

	//改变锥形波束的目标点,mt=波束的节点,latitude, longitude, height目标点的坐标,ifDynamic=是否打开动态跟踪,如果是false,则波束只会改变一次朝向,模型运动的时候,波束的方向不变,如果为true,则波束会跟踪目标点,实现动态的方向更改。
	void changeWaveBeamConeTarget(/*osg::MatrixTransform* mt,*/ double latitude, double longitude, double height, bool ifDynamic);

	//改变锥形波束的外观,color=波束颜色 lineColor=线的颜色 lineWidth=线的宽度 注意最后一个参数线宽,如果小于0.1,则线会被隐藏
	void changeWaveBeamConeAppearance(osg::Vec4 color, osg::Vec4 lineColor, double lineWidth);

	osg::ref_ptr<osg::MatrixTransform> getWaveBeamCone() {
		return _waveBeamCone;
	}
private:
	osg::ref_ptr<osg::MatrixTransform> _waveBeamCone;
};


#include "WaveBeamCone.h"
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osgFX/Outline>
#include <osgFX/Scribe>
#include <osg/MatrixTransform>
#include "WaveBeamConeCallBack.h"
#include "EarthMapManager.h"

WaveBeamCone::WaveBeamCone() :Pendant(PST3D_WAVEBEAN_CONE) {
}

WaveBeamCone::~WaveBeamCone() {
}

void WaveBeamCone::clearSelf() {

}

void WaveBeamCone::createWaveBeamCone(osg::MatrixTransform* node, double angle, double length, osg::Vec4 color, osg::Vec4 lineColor, double lineWidth) {
	double angleD = osg::DegreesToRadians(angle);
	double radius = std::tan(angleD*0.5) * length;
	int splitCount = 20;
	double angleStep = osg::PI * 2.0 / splitCount;


	osg::ref_ptr<osg::Geode> geode = new osg::Geode();
	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
	osg::ref_ptr<osg::Vec3Array> vertex = new osg::Vec3Array;
	osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array;
	osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLE_FAN);
	osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt2 = new osg::DrawElementsUInt(GL_TRIANGLE_FAN);
	geom->setVertexArray(vertex);
	geom->setNormalArray(normal);
	geode->addDrawable(geom);

	vertex->push_back(osg::Vec3(0, 0, 0));
	drawElemUInt->push_back(0);
	normal->push_back(osg::Vec3(0, -1, 0));

	//侧面
	for (int i = 0; i <= splitCount; i++) {
		double tempAngle = i*angleStep;
		osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
		vertex->push_back(osg::Vec3(pos));

		pos.normalize();
		normal->push_back(pos);
		drawElemUInt->push_back(i + 1);
	}

	//底面
	int indexBegin = vertex->size();
	vertex->push_back(osg::Vec3(0, length, 0));
	drawElemUInt2->push_back(indexBegin);
	normal->push_back(osg::Vec3(0, 1, 0));
	for (int i = 0; i <= splitCount; i++) {
		double tempAngle = i*angleStep;
		osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
		vertex->push_back(osg::Vec3(pos));

		normal->push_back(osg::Vec3(0, 1, 0));
		drawElemUInt2->push_back(indexBegin + i + 1);
	}


	geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
	geom->addPrimitiveSet(drawElemUInt);
	geom->addPrimitiveSet(drawElemUInt2);

	//创建材质对象
	osg::ref_ptr<osg::Material> mat = new osg::Material;
	//设置正面散射颜色
	mat->setDiffuse(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3
	//设置正面镜面颜色
	mat->setSpecular(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3

	geode->getOrCreateStateSet()->setAttribute(mat.get());
	geode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
	//设置透明效果
	geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
	geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
	geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

	//设置渲染顺序 仿真模型被波束遮盖 ,1000000-指的是若有1000000个Node 则此节点最后一个被渲染
	geode->getOrCreateStateSet()->setRenderBinDetails(1000000, "RenderBin");

	osg::ref_ptr<osgFX::Scribe>  nodeFX = new osgFX::Scribe;
	nodeFX->setWireframeColor(lineColor);
	nodeFX->setWireframeLineWidth(lineWidth);
	nodeFX->addChild(geode);

	osg::ref_ptr<osg::MatrixTransform> mtCone = new osg::MatrixTransform;
	mtCone->addChild(nodeFX);

	//给callback中赋值
	WaveBeamConeCallBack* coneCallBack = new WaveBeamConeCallBack;
	coneCallBack->m_angle = angle;
	coneCallBack->m_length = length;
	coneCallBack->m_color = color;
	coneCallBack->m_lineColor = lineColor;
	coneCallBack->m_lineWidth = lineWidth;

	coneCallBack->m_geode = geode;
	coneCallBack->m_geom = geom;
	coneCallBack->m_pointVector = vertex;
	coneCallBack->m_nodeFX = nodeFX;

	//如果线宽小于0.1,则关闭线框显示效果
	if (lineWidth < 0.1) {
		mtCone->addChild(coneCallBack->m_geode);
		mtCone->removeChild(coneCallBack->m_nodeFX);
	} else {
		mtCone->removeChild(coneCallBack->m_geode);
		mtCone->addChild(coneCallBack->m_nodeFX);
	}

	mtCone->setUpdateCallback(coneCallBack);
	mtCone->addDescription("WaveBeamCone");

	//添加到模型中
	osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(node->getChild(0));
	osg::MatrixTransform* mtS = dynamic_cast<osg::MatrixTransform*>(mtR->getChild(0));
	mtR->addChild(mtCone);
	_waveBeamCone = mtCone;
}

void WaveBeamCone::changeWaveBeamConeTarget(double latitude, double longitude, double height, bool ifDynamic) {
	WaveBeamConeCallBack* coneCallBack = dynamic_cast<WaveBeamConeCallBack*>(_waveBeamCone->getUpdateCallback());
	if (coneCallBack != NULL) {
		coneCallBack->m_ifDynamic = ifDynamic;
		coneCallBack->m_latitude = latitude;
		coneCallBack->m_longitude = longitude;
		coneCallBack->m_height = height;

		if (ifDynamic == false) {
			osg::MatrixTransform* mtCone = _waveBeamCone;

			osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(mtCone->getParent(0));
			osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(mtR->getParent(0));

			//osg::Matrix m = osg::computeWorldToLocal(mtCone->getParentalNodePaths().at(0));
			osg::Matrix m = osg::Matrix::inverse(mt->getMatrix()*mtR->getMatrix());
			osg::Matrix mTarget;
			double x, y, z;
			EarthMapMgr()->getMapNode()->getMapSRS()->getEllipsoid()->convertLatLongHeightToXYZ(osg::DegreesToRadians(latitude),
				osg::DegreesToRadians(longitude),
				height, x, y, z);

			mTarget.setTrans(x, y, z);
			osg::Matrix mConeRate = osg::Matrix::rotate(osg::Vec3d(0, 1, 0), (mTarget*m).getTrans());

			mtCone->setMatrix(mConeRate);
		}
	}
}

void WaveBeamCone::changeWaveBeamConeAppearance( osg::Vec4 color, osg::Vec4 lineColor, double lineWidth) {
	WaveBeamConeCallBack* coneCallBack = dynamic_cast<WaveBeamConeCallBack*>(_waveBeamCone->getUpdateCallback());
	if (coneCallBack != NULL) {
		coneCallBack->m_color = color;
		coneCallBack->m_lineColor = lineColor;
		coneCallBack->m_lineWidth = lineWidth;

		//创建材质对象
		osg::ref_ptr<osg::Material> mat = new osg::Material;
		//设置正面散射颜色
		mat->setDiffuse(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3
		//设置正面镜面颜色
		mat->setSpecular(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3					  
		coneCallBack->m_geode->getOrCreateStateSet()->setAttribute(mat.get());

		if (lineWidth < 0.1) {
			_waveBeamCone->addChild(coneCallBack->m_geode);
			_waveBeamCone->removeChild(coneCallBack->m_nodeFX);
		} else {
			_waveBeamCone->removeChild(coneCallBack->m_geode);
			_waveBeamCone->addChild(coneCallBack->m_nodeFX);

			coneCallBack->m_nodeFX->setWireframeColor(lineColor);
			coneCallBack->m_nodeFX->setWireframeLineWidth(lineWidth);
		}
	}
}

#pragma once
#include <osg/Geometry>
#include <osgFX/Scribe>
#include <osg/NodeCallback>

class WaveBeamConeCallBack : public osg::NodeCallback {
public:
	WaveBeamConeCallBack();
	~WaveBeamConeCallBack();

	virtual void operator() (osg::Node *node, osg::NodeVisitor *nv);
public:
	double m_latitude;
	double m_longitude;
	double m_height;
	bool m_ifDynamic;

	double m_angle;
	double m_length;
	osg::Vec4 m_color;
	osg::Vec4 m_lineColor;
	double m_lineWidth;

	osg::ref_ptr<osg::Geode> m_geode;
	osg::ref_ptr<osg::Geometry> m_geom;
	osg::ref_ptr<osg::Vec4Array> m_colorArray;
	osg::ref_ptr<osg::Vec3Array> m_pointVector;
	osg::ref_ptr<osgFX::Scribe> m_nodeFX;
};


#include "WaveBeamConeCallBack.h"
#include "EarthMapManager.h"
#include <osg/MatrixTransform>

WaveBeamConeCallBack::WaveBeamConeCallBack() {
	m_latitude = 0.0;
	m_longitude = 0.0;
	m_height = -6371000;
	m_ifDynamic = false;

	m_angle = 20.0;
	m_length = 100000;
	m_color = osg::Vec4(1, 0, 0, 0.5);
	m_lineColor = osg::Vec4(1.0, 0.0, 0.0, 1.0);
	m_lineWidth = 1.0;
}


WaveBeamConeCallBack::~WaveBeamConeCallBack() {
}


void WaveBeamConeCallBack::operator()(osg::Node *node, osg::NodeVisitor *nv) {
	if (m_ifDynamic == false)
		return;
	//std::cout << "WaveBeamConeCallBack info=" << m_latitude << "," << m_longitude << "," << m_height << std::endl;
	osg::MatrixTransform* mtCone = dynamic_cast<osg::MatrixTransform*>(node);
	if (mtCone != NULL) {
		osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(mtCone->getParent(0));
		osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(mtR->getParent(0));

		//osg::Matrix m = osg::computeWorldToLocal(mtCone->getParentalNodePaths().at(0));
		osg::Matrix m = osg::Matrix::inverse(mt->getMatrix()*mtR->getMatrix());
		osg::Matrix mTarget;
		double x, y, z;
		EarthMapMgr()->getMapNode()->getMapSRS()->getEllipsoid()->convertLatLongHeightToXYZ(osg::DegreesToRadians(m_latitude),
			osg::DegreesToRadians(m_longitude),
			m_height, x, y, z);

		mTarget.setTrans(x, y, z);
		osg::Matrix mConeRate = osg::Matrix::rotate(osg::Vec3d(0, 1, 0), (mTarget*m).getTrans());
		mtCone->setMatrix(mConeRate);//mTarget*m

		//更改cone的形状----------------------------------------
		double length = (mTarget*m).getTrans().length();

		double angle = osg::DegreesToRadians(m_angle);
		double radius = std::tan(angle*0.5) * length;
		int splitCount = 20;
		double angleStep = osg::PI * 2.0 / splitCount;

		//侧面
		for (int i = 1; i <= splitCount + 1; i++) {
			double tempAngle = (i - 1)*angleStep;
			osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
			m_pointVector->at(i) = pos;
		}

		m_pointVector->at(splitCount + 2) = osg::Vec3(0, length, 0);

		//底面
		for (int i = splitCount + 3; i <= splitCount + 3 + splitCount; i++) {
			double tempAngle = (i - splitCount - 3) *angleStep;
			osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
			m_pointVector->at(i) = pos;
		}

		m_geom->dirtyBound();
		m_geom->dirtyDisplayList();
	}
}

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wb175208

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

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

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

打赏作者

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

抵扣说明:

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

余额充值