DYTSrouce/src/effects/ConeWave.cpp
2025-02-22 23:16:54 +08:00

524 lines
17 KiB
C++

#include "effects/ConeWave.h"
/*
#include <osg/BlendFunc>
#include <osg/Material>
#include <osg/Texture2D>
#include <osg/ShapeDrawable>
#include <osg/Group>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Shader>
#include <osg/Program>
#include <osg/Uniform>
#include <osg/Depth>
#include <osgEarth/Registry>
class WaveSurfaceCallback : public osg::NodeCallback {
public:
WaveSurfaceCallback() : timeElapsed(0.0f) {}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
timeElapsed += (nv->getFrameStamp()->getSimulationTime() - SimulationTime);
// 获取并更新geometry的顶点
osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
if (geode) {
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(geode->getDrawable(0));
if (geometry) {
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
if (vertices) {
// 更新顶点位置来模拟波动
float amplitude = 2.0f;
float frequency = 1.0f;
for (unsigned int i = 0; i < vertices->size(); ++i) {
osg::Vec3f& vertex = (*vertices)[i];
vertex.z() = amplitude * sin(frequency * (vertex.x() + timeElapsed));
}
geometry->setVertexArray(vertices);
geometry->dirtyBound(); // 更新几何体边界
}
}
}
// 继续遍历场景图
traverse(node, nv);
SimulationTime = nv->getFrameStamp()->getSimulationTime();
}
private:
float timeElapsed;
double SimulationTime;
};
ConeWave::ConeWave() {
osgEarth::Registry::shaderGenerator().run(this);
}
ConeWave::~ConeWave(void)
{
}
void ConeWave::Render(double dt) {
}
void ConeWave::InitGeode() {
CreateTexturedCone(this);
//getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
//getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
//getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
//setCullingActive(false);
}
void ConeWave::Destory() {
OnDestroy();
}
void ConeWave::SetHeight(float height) {
height_ = height;
if (cone_) {
cone_->setHeight(height_);
}
// coneDrawable_->build();
}
void ConeWave::SetRadius(float radius) {
radius_ = radius;
if (cone_) {
cone_->setRadius(radius);
}
// coneDrawable_->build();
}
void ConeWave::SetBaseColor(const osg::Vec4& color) {
baseColor_ = color;
if (baseColorUniform_) {
baseColorUniform_->set(color);
}
}
void ConeWave::SetLevelCount(int count) {
levelCount_ = count;
if (levelCountUniform_) {
levelCountUniform_->set(float(levelCount_));
}
}
void ConeWave::SetLevelHeight(float height) {
levelHeight_ = height;
if (levelHeightUniform_) {
levelHeightUniform_->set(levelHeight_);
}
}
void ConeWave::CreateTexturedCone(osg::Geode* geode) {
// cone_ = new osg::Cone(osg::Vec3(0, 0, 0.), radius_, height_);
// osg::TessellationHints* tesselate = new osg::TessellationHints;
// tesselate->setCreateBottom(false);
// tesselate->setCreateBackFace(false);
// coneDrawable_ = new osg::ShapeDrawable(cone_, tesselate);
// geode->addDrawable(coneDrawable_);
// coneDrawable_->setColor(baseColor_);
// osg::StateSet* ss = coneDrawable_->getOrCreateStateSet();
// //stateset->setRenderBinDetails(120, "OSGEARTH_SCREEN_SPACE_LAYOUT_BIN");
// ss->setRenderBinDetails(120, "RenderBin");
// osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc();
// ss->setAttributeAndModes(bf, osg::StateAttribute::ON);
// ss->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
// 创建顶点数组
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
int rows = 20, cols=20;
for (unsigned int i = 0; i < rows; ++i) {
for (unsigned int j = 0; j < cols; ++j) {
// 坐标
float x = (float)i / (rows - 1) * 100;
float y = (float)j / (cols - 1) * 100;
vertices->push_back(osg::Vec3f(x, y, 0.0f));
}
}
geometry->setVertexArray(vertices);
// 生成索引来连接顶点
osg::ref_ptr<osg::DrawElementsUShort> indices = new osg::DrawElementsUShort(osg::PrimitiveSet::QUADS);
for (unsigned int i = 0; i < rows - 1; ++i) {
for (unsigned int j = 0; j < cols - 1; ++j) {
unsigned short bottomLeft = i * cols + j;
unsigned short bottomRight = bottomLeft + 1;
unsigned short topLeft = (i + 1) * cols + j;
unsigned short topRight = topLeft + 1;
indices->push_back(bottomLeft);
indices->push_back(bottomRight);
indices->push_back(topRight);
indices->push_back(topLeft);
}
}
geometry->addPrimitiveSet(indices);
// 创建表面颜色
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); // 蓝色
geometry->setColorArray(colors);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
// 添加geometry到geode
geode->addDrawable(geometry);
geode->setUpdateCallback(new WaveSurfaceCallback());
return;
static const char* vertSource = {
"#version 330\n"
"varying vec3 pos;\n"
"void main()\n"
"{\n"
"pos.x=gl_Vertex.x;\n"
"pos.y=gl_Vertex.y;\n"
"pos.z=gl_Vertex.z;\n"
"gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;\n"
"}\n"
};
static const char* fragSource = {
"#version 330\n"
"uniform float num; \n"
"uniform float height; \n"
"uniform vec4 baseColor;\n"
"varying vec3 pos;\n"
"float Alpha = 1.0; \n"
"float f = pos.z;\n"
"uniform float osg_FrameTime;\n"
"void main()\n"
"{\n"
"if (sin(f/height*3.14*2*num+ osg_FrameTime*10) > 0)\n"
"{\n"
" Alpha = 0.8;\n"
"}\n"
"else\n"
"{\n"
" Alpha = 0.3;\n"
"}\n"
" gl_FragColor = vec4(baseColor.rgb, Alpha);\n"
"}\n "
};
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX);
vertexShader->setShaderSource(vertSource);
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT);
fragmentShader->setShaderSource(fragSource);
osg::StateSet* stateset = coneDrawable_->getOrCreateStateSet();
// osg::ref_ptr<osg::Material> mat = new osg::Material;
// //设置正面散射颜色
// mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
// //设置正面镜面颜色
// mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
//
// geode->getOrCreateStateSet()->setAttribute(mat);
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
// stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
//设置渲染顺序 仿真模型被波束遮盖 ,1000000-指的是若有1000000个Node 则此节点最后一个被渲染
// //stateset->setRenderBinDetails(120, "OSGEARTH_SCREEN_SPACE_LAYOUT_BIN");
stateset->setRenderBinDetails(10, "RenderBin");
// osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc();
// stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
// osg::ref_ptr<osg::Program> program = new osg::Program();
// program->addShader(vertexShader);
// program->addShader(fragmentShader);
//
// baseColorUniform_ = new osg::Uniform("baseColor", baseColor_);
// stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
// stateset->addUniform(baseColorUniform_);
// // stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
// // stateset->setAttributeAndModes(new osg::Depth(osg::Depth::LESS, 0.0, 1.0, false));
//
// levelCountUniform_ = new osg::Uniform("num", float(levelCount_));
// levelHeightUniform_ = new osg::Uniform("height", levelHeight_);
// stateset->addUniform(levelCountUniform_);
// stateset->addUniform(levelHeightUniform_.get());
}
*/
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osgFX/Outline>
#include <osgFX/Scribe>
#include <osg/MatrixTransform>
#include <osgEarth/Ellipsoid>
#include "scene/SceneContent.h"
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;
};
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;
osg::EllipsoidModel em;
em.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();
}
}
ConeWave::ConeWave() {
}
ConeWave::~ConeWave() {
}
void ConeWave::clearSelf() {
}
void ConeWave::Render(double dt)
{
}
void ConeWave::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, osg::Vec4(1.0, 1.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
//设置正面镜面颜色
mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//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(12, "RenderBin");
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;
//添加到模型中
// 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 ConeWave::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;
osg::EllipsoidModel em;
em.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 ConeWave::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);
}
}
}