diff --git a/src/effects/ConeWave.cpp b/src/effects/ConeWave.cpp index cea46eef..7887a27f 100644 --- a/src/effects/ConeWave.cpp +++ b/src/effects/ConeWave.cpp @@ -50,9 +50,41 @@ private: double SimulationTime; }; +// 雷达扫描波时间更新回调 +class RadarWaveTimeCallback : public osg::NodeCallback { +public: + RadarWaveTimeCallback(osg::ref_ptr waveTimeUniform) + : waveTimeUniform_(waveTimeUniform), startTime_(0.0) {} + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { + if (nv->getFrameStamp()) { + double currentTime = nv->getFrameStamp()->getSimulationTime(); + if (startTime_ == 0.0) { + startTime_ = currentTime; + } + + // 计算经过的时间 + float elapsedTime = static_cast(currentTime - startTime_); + + // 更新waveTime uniform + if (waveTimeUniform_.valid()) { + waveTimeUniform_->set(elapsedTime); + } + } + + // 继续遍历场景图 + traverse(node, nv); + } + +private: + osg::ref_ptr waveTimeUniform_; + double startTime_; +}; + ConeWave::ConeWave() { osgEarth::Registry::shaderGenerator().run(this); + currentTime_ = 0.0; } @@ -61,14 +93,16 @@ ConeWave::~ConeWave(void) } void ConeWave::Render(double dt) { - + // 时间更新现在由RadarWaveTimeCallback回调处理 + // 这里可以处理其他需要更新的属性 } void ConeWave::InitGeode() { - CreateTexturedCone(this); + CreateRadarScanWave(); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); setCullingActive(false); } @@ -81,7 +115,7 @@ void ConeWave::SetHeight(float height) { if (cone_) { cone_->setHeight(height_); } - // coneDrawable_->build(); + //coneDrawable_->build(); } void ConeWave::SetRadius(float radius) { @@ -113,84 +147,153 @@ void ConeWave::SetLevelHeight(float height) { } } -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 bf = new osg::BlendFunc(); - // ss->setAttributeAndModes(bf, osg::StateAttribute::ON); - // ss->setMode(GL_CULL_FACE, osg::StateAttribute::ON); +// 雷达扫描波效果相关方法实现 +void ConeWave::SetWaveRadius(float radius) { + waveRadius_ = radius; + if (waveRadiusUniform_.valid()) { + waveRadiusUniform_->set(radius); + } + // 更新Cone的半径以匹配扫描波半径 + if (cone_.valid()) { + cone_->setRadius(radius); + // 强制更新ShapeDrawable + if (coneDrawable_.valid()) { + coneDrawable_->dirtyDisplayList(); + coneDrawable_->dirtyBound(); + } + } +} + +void ConeWave::SetWaveSpeed(float speed) { + waveSpeed_ = speed; + if (waveSpeedUniform_.valid()) { + waveSpeedUniform_->set(speed); + } +} + +void ConeWave::SetWaveCount(int count) { + waveCount_ = count; + if (waveCountUniform_.valid()) { + waveCountUniform_->set(static_cast(count)); + } +} + +void ConeWave::SetWaveColor(const osg::Vec4& color) { + waveColor_ = color; + if (waveColorUniform_.valid()) { + waveColorUniform_->set(color); + } +} + +void ConeWave::CreateRadarScanWave() { + // 使用OSG内置的Cone几何体来创建雷达扫描区域 + cone_ = new osg::Cone(osg::Vec3(0, 0, 0.), waveRadius_, height_); + // 设置细分参数,创建更平滑的圆形底面 + osg::TessellationHints* tesselate = new osg::TessellationHints; + tesselate->setCreateBottom(true); // 创建底面作为扫描面 + tesselate->setCreateBackFace(false); // 不创建背面 + tesselate->setDetailRatio(2.0f); // 增加细分精度 + + // 创建可绘制对象 + coneDrawable_ = new osg::ShapeDrawable(cone_, tesselate); + coneDrawable_->setColor(waveColor_); + + // 添加到几何节点 + addDrawable(coneDrawable_); + + // 设置渲染状态 + osg::StateSet* ss = coneDrawable_->getOrCreateStateSet(); + ss->setRenderBinDetails(120, "RenderBin"); + ss->setMode(GL_CULL_FACE, osg::StateAttribute::ON); + + // 设置混合模式 + osg::ref_ptr bf = new osg::BlendFunc(); + ss->setAttributeAndModes(bf, osg::StateAttribute::ON); + ss->setMode(GL_BLEND, osg::StateAttribute::ON); + ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + + // 创建雷达扫描波着色器 + CreateRadarShader(); + + // 添加时间更新回调 + setUpdateCallback(new RadarWaveTimeCallback(waveTimeUniform_)); +} - osg::ref_ptr geometry = new osg::Geometry(); - - // 创建顶点数组 - osg::ref_ptr 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 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 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" +void ConeWave::CreateRadarShader() { + // 顶点着色器 - 使用简单的基于高度的条纹效果 + static const char* vertexShaderSource = "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" + " 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* fragmentShaderSource = + "uniform float num;\n" + "uniform float height;\n" + "uniform vec4 baseColor;\n" + "uniform vec4 waveColor;\n" + "uniform float waveTime;\n" + "varying vec3 pos;\n" + "void main()\n" + "{\n" + " // 基于高度的层次效果\n" + " float h = abs(pos.z) / height;\n" + " float layer = h * num + waveTime;\n" + " \n" + " // 简单的波纹效果\n" + " float wave = sin(layer * 6.28);\n" + " float pulse = (wave + 1.0) * 0.5;\n" + " \n" + " // 计算边缘\n" + " float dist = sqrt(pos.x * pos.x + pos.y * pos.y);\n" + " float maxDist = abs(pos.z) * 1.2;\n" + " float edge = dist / maxDist;\n" + " \n" + " // 层次线效果\n" + " float layerLine = sin(h * num * 6.28 + waveTime * 4.0);\n" + " float lineIntensity = (layerLine + 1.0) * 0.5;\n" + " \n" + " // 颜色选择\n" + " if (lineIntensity > 0.7 && edge < 1.0)\n" + " {\n" + " // 黄色边框线\n" + " gl_FragColor = vec4(1.0, 1.0, 0.0, 0.9);\n" + " }\n" + " else if (edge < 1.0)\n" + " {\n" + " // 基础锥形区域\n" + " float intensity = pulse * 0.6 + 0.3;\n" + " gl_FragColor = vec4(baseColor.rgb * intensity, 0.4 * intensity);\n" + " }\n" + " else\n" + " {\n" + " // 超出边界\n" + " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" + " }\n" + "}\n"; + /* + + static const char* vertexShaderSource = { + "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" + static const char* fragmentShaderSource = { "uniform float num; \n" "uniform float height; \n" - "uniform vec4 baseColor;\n" + "uniform vec4 waveColor;\n" + "uniform vec4 baseColor; \n" "varying vec3 pos;\n" "float Alpha = 1.0; \n" "float f = pos.z;\n" @@ -208,6 +311,128 @@ void ConeWave::CreateTexturedCone(osg::Geode* geode) { " gl_FragColor = vec4(baseColor.rgb, Alpha);\n" "}\n " }; +*/ + // 创建着色器 + osg::ref_ptr vertexShader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource); + osg::ref_ptr fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource); + + osg::ref_ptr program = new osg::Program; + program->addShader(vertexShader); + program->addShader(fragmentShader); + + // 获取drawable的状态集并设置着色器程序 + osg::StateSet* stateSet = coneDrawable_->getOrCreateStateSet(); + stateSet->setAttributeAndModes(program, osg::StateAttribute::ON); + + // 创建uniform变量 + waveTimeUniform_ = new osg::Uniform("waveTime", 0.0f); + baseColorUniform_ = new osg::Uniform("baseColor", osg::Vec4(0.8f, 0.2f, 0.2f, 1.0f)); // 红色基调 + waveColorUniform_ = new osg::Uniform("waveColor", waveColor_); + levelCountUniform_ = new osg::Uniform("num", 8.0f); // 增加层数 + levelHeightUniform_ = new osg::Uniform("height", height_); + + stateSet->addUniform(waveTimeUniform_); + stateSet->addUniform(baseColorUniform_); + stateSet->addUniform(waveColorUniform_); + stateSet->addUniform(levelCountUniform_); + stateSet->addUniform(levelHeightUniform_); +} + +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 bf = new osg::BlendFunc(); + ss->setAttributeAndModes(bf, osg::StateAttribute::ON); + ss->setMode(GL_CULL_FACE, osg::StateAttribute::ON); + + + //osg::ref_ptr geometry = new osg::Geometry(); + + //// 创建顶点数组 + //osg::ref_ptr 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 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 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 vertexShader = new osg::Shader(osg::Shader::VERTEX); vertexShader->setShaderSource(vertSource); diff --git a/src/effects/ConeWave.h b/src/effects/ConeWave.h index f54cfc39..87609bbe 100644 --- a/src/effects/ConeWave.h +++ b/src/effects/ConeWave.h @@ -20,6 +20,21 @@ public: void InitGeode(); void Destory(); + // 雷达扫描波效果相关方法 + void CreateRadarScanWave(); + void CreateRadarShader(); + void SetWaveRadius(float radius); + float GetWaveRadius() const { return waveRadius_; } + + void SetWaveSpeed(float speed); + float GetWaveSpeed() const { return waveSpeed_; } + + void SetWaveCount(int count); + int GetWaveCount() const { return waveCount_; } + + void SetWaveColor(const osg::Vec4& color); + const osg::Vec4& GetWaveColor() const { return waveColor_; } + void SetHeight(float height); float GetHeght() const { return height_; @@ -52,14 +67,27 @@ private: osg::ref_ptr cone_; osg::ref_ptr coneDrawable_; osg::ref_ptr baseColorUniform_; - osg::Vec4 baseColor_{ 0.0f, 0.2f, 0.5f, 0.2f }; osg::ref_ptr levelCountUniform_; int levelCount_{ 4 }; osg::ref_ptr levelHeightUniform_; float levelHeight_{ 500.0f }; - float height_{ 60.0f }; + float height_{ 6.0f }; float radius_{ 10.0f }; + + // 雷达扫描波效果相关成员变量 + osg::ref_ptr waveTimeUniform_; + osg::ref_ptr waveRadiusUniform_; + osg::ref_ptr waveSpeedUniform_; + osg::ref_ptr waveCountUniform_; + osg::ref_ptr waveColorUniform_; + + float waveRadius_{ 100.0f }; // 扫描波最大半径 + float waveSpeed_{ 20.0f }; // 扫描波速度 + int waveCount_{ 30 }; // 同时存在的波纹数量 + osg::Vec4 baseColor_{ 1.0f, 0.2f, 0.5f, 1.f }; + osg::Vec4 waveColor_{ 0.0f, 0.5f, 1.0f, 0.8f }; // 扫描波颜色(蓝色) + double currentTime_{ 0.0 }; // 当前时间 }; /* diff --git a/src/entities/ConeWaveComponent.cpp b/src/entities/ConeWaveComponent.cpp index b4b0258a..6ee8e3fe 100644 --- a/src/entities/ConeWaveComponent.cpp +++ b/src/entities/ConeWaveComponent.cpp @@ -46,6 +46,14 @@ bool ConeWaveComponent::SetAttribute(const char* name, const char* value) { SetLevelCount(atof(value)); } else if (0 == strcmp("levelHeihgt", name)) { SetLevelHeight(atof(value)); + } else if (0 == strcmp("waveRadius", name)) { + SetWaveRadius(atof(value)); + } else if (0 == strcmp("waveSpeed", name)) { + SetWaveSpeed(atof(value)); + } else if (0 == strcmp("waveCount", name)) { + SetWaveCount(atoi(value)); + } else if (0 == strcmp("waveColor", name)) { + SetWaveColor(StringUtils::StringToVec4(value)); } return SceneComponent::SetAttribute(name, value); @@ -81,6 +89,10 @@ void ConeWaveComponent::Begin() { void ConeWaveComponent::Update(double dt) { UpdateEvent(); + // 更新雷达扫描波效果 + if (coneWave_.valid()) { + coneWave_->Render(dt); + } } void ConeWaveComponent::SetHeight(float height) { @@ -223,3 +235,57 @@ void ConeWaveComponent::AddColor(int32_t status, const osg::Vec4& color) { colorMap_[status] = color; } +// 雷达扫描波效果相关方法实现 +void ConeWaveComponent::SetWaveRadius(float radius) { + if (coneWave_.valid()) { + coneWave_->SetWaveRadius(radius); + } +} + +float ConeWaveComponent::GetWaveRadius() const { + if (coneWave_.valid()) { + return coneWave_->GetWaveRadius(); + } + return 0.0f; +} + +void ConeWaveComponent::SetWaveSpeed(float speed) { + if (coneWave_.valid()) { + coneWave_->SetWaveSpeed(speed); + } +} + +float ConeWaveComponent::GetWaveSpeed() const { + if (coneWave_.valid()) { + return coneWave_->GetWaveSpeed(); + } + return 0.0f; +} + +void ConeWaveComponent::SetWaveCount(int count) { + if (coneWave_.valid()) { + coneWave_->SetWaveCount(count); + } +} + +int ConeWaveComponent::GetWaveCount() const { + if (coneWave_.valid()) { + return coneWave_->GetWaveCount(); + } + return 0; +} + +void ConeWaveComponent::SetWaveColor(const osg::Vec4& color) { + if (coneWave_.valid()) { + coneWave_->SetWaveColor(color); + } +} + +const osg::Vec4& ConeWaveComponent::GetWaveColor() const { + static osg::Vec4 defaultColor(0.0f, 0.5f, 1.0f, 0.8f); + if (coneWave_.valid()) { + return coneWave_->GetWaveColor(); + } + return defaultColor; +} + diff --git a/src/entities/ConeWaveComponent.h b/src/entities/ConeWaveComponent.h index 0c2ed04b..c41ef42e 100644 --- a/src/entities/ConeWaveComponent.h +++ b/src/entities/ConeWaveComponent.h @@ -49,6 +49,19 @@ public: void SetColor3(const osg::Vec4& color); const osg::Vec4 GetColor3() const; + // 雷达扫描波效果相关方法 + void SetWaveRadius(float radius); + float GetWaveRadius() const; + + void SetWaveSpeed(float speed); + float GetWaveSpeed() const; + + void SetWaveCount(int count); + int GetWaveCount() const; + + void SetWaveColor(const osg::Vec4& color); + const osg::Vec4& GetWaveColor() const; + void SetTimeAction(const QString& path); protected: