From 09767ecdbdd290934c928bc3c2e54750fa7af629 Mon Sep 17 00:00:00 2001 From: brige Date: Fri, 27 Jun 2025 08:29:36 +0800 Subject: [PATCH] add rebuild cone wave --- src/effects/ConeWave.cpp | 203 +++++++++++++++++------------ src/effects/ConeWave.h | 11 +- src/entities/ConeWaveComponent.cpp | 4 - 3 files changed, 127 insertions(+), 91 deletions(-) diff --git a/src/effects/ConeWave.cpp b/src/effects/ConeWave.cpp index 666842cc..6a67c359 100644 --- a/src/effects/ConeWave.cpp +++ b/src/effects/ConeWave.cpp @@ -113,7 +113,7 @@ void ConeWave::Render(double dt) { } void ConeWave::InitGeode() { - CreateRadarScanWave(); + Rebuild(); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); @@ -127,32 +127,13 @@ void ConeWave::Destory() { void ConeWave::SetHeight(float height) { height_ = height; - if (cone_.valid()) { - cone_->setHeight(height_); - // 更新锥形中心位置以保持顶点在原点 - cone_->setCenter(osg::Vec3(0, 0, -height_/2)); - // 强制更新ShapeDrawable - if (coneDrawable_.valid()) { - coneDrawable_->dirtyDisplayList(); - coneDrawable_->dirtyBound(); - } - } - // 确保着色器已经初始化 - if (!levelHeightUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } - // 更新着色器中的高度uniform - if (levelHeightUniform_.valid()) { - levelHeightUniform_->set(height_ > 0 ? height_ : 100.0f); - } + + Rebuild(); } void ConeWave::SetBaseColor(const osg::Vec4& color) { baseColor_ = color; - // 确保着色器已经初始化 - if (!baseColorUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } + if (baseColorUniform_.valid()) { baseColorUniform_->set(baseColor_); } @@ -160,23 +141,12 @@ void ConeWave::SetBaseColor(const osg::Vec4& color) { void ConeWave::SetWaveCount(int count) { waveCount_ = count; - // 确保着色器已经初始化 - if (!waveCountUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } - - if (waveCountUniform_.valid()) { - waveCountUniform_->set(static_cast(waveCount_)); - } + Rebuild(); } void ConeWave::SetWaveSpeed(float speed) { waveSpeed_ = speed; - // 确保着色器已经初始化 - if (!waveSpeedUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } - + if (waveSpeedUniform_.valid()) { waveSpeedUniform_->set(waveSpeed_); } @@ -185,30 +155,13 @@ void ConeWave::SetWaveSpeed(float speed) { // 雷达扫描波效果相关方法实现 void ConeWave::SetWaveRadius(float radius) { waveRadius_ = radius; - // 确保着色器已经初始化 - if (!waveRadiusUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } - if (waveRadiusUniform_.valid()) { - waveRadiusUniform_->set(radius); - } - // 更新Cone的半径以匹配扫描波半径 - if (cone_.valid()) { - cone_->setRadius(radius); - // 强制更新ShapeDrawable - if (coneDrawable_.valid()) { - coneDrawable_->dirtyDisplayList(); - coneDrawable_->dirtyBound(); - } - } + radius_ = radius; // 同时更新锥形的半径 + Rebuild(); } void ConeWave::SetWaveColor(const osg::Vec4& color) { waveColor_ = color; - // 确保着色器已经初始化 - if (!waveColorUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } + if (waveColorUniform_.valid()) { waveColorUniform_->set(waveColor_); } @@ -217,10 +170,7 @@ void ConeWave::SetWaveColor(const osg::Vec4& color) { // 透明度控制方法实现 void ConeWave::SetRingBrightAlpha(float alpha) { ringBrightAlpha_ = alpha; - // 确保着色器已经初始化 - if (!ringBrightAlphaUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } + if (ringBrightAlphaUniform_.valid()) { ringBrightAlphaUniform_->set(alpha); } @@ -228,10 +178,6 @@ void ConeWave::SetRingBrightAlpha(float alpha) { void ConeWave::SetRingDarkAlpha(float alpha) { ringDarkAlpha_ = alpha; - // 确保着色器已经初始化 - if (!ringDarkAlphaUniform_.valid() && coneDrawable_.valid()) { - CreateRadarShader(); - } if (ringDarkAlphaUniform_.valid()) { ringDarkAlphaUniform_->set(alpha); } @@ -240,31 +186,116 @@ void ConeWave::SetRingDarkAlpha(float alpha) { void ConeWave::SetConeAlpha(float alpha) { coneAlpha_ = alpha; // 更新锥形的基础颜色透明度 - if (coneDrawable_.valid()) { - osg::Vec4 currentColor = coneDrawable_->getColor(); - currentColor.a() = alpha; - coneDrawable_->setColor(currentColor); + if (coneGeometry_.valid()) { + // 通过着色器uniform来控制透明度,而不是直接设置颜色 + // 这里可以在CreateRadarShader中添加coneAlpha uniform来控制 + // 或者通过StateSet的材质属性来控制 + osg::StateSet* ss = coneGeometry_->getOrCreateStateSet(); + osg::ref_ptr material = new osg::Material(); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.8f, 1.0f, alpha)); + material->setTransparency(osg::Material::FRONT_AND_BACK, 1.0f - alpha); + ss->setAttributeAndModes(material, osg::StateAttribute::ON); + } +} + +void ConeWave::Clear() { + // 清除锥形几何体和相关uniform + if (coneCallback_.valid()) { + setUpdateCallback(nullptr); // 移除时间更新回调 + coneCallback_ = nullptr; + } + + if (coneGeometry_.valid()) { + removeDrawable(coneGeometry_); + coneGeometry_ = nullptr; + coneDrawable_ = nullptr; + } + + waveTimeUniform_ = nullptr; + baseColorUniform_ = nullptr; + waveColorUniform_ = nullptr; + levelHeightUniform_ = nullptr; + waveSpeedUniform_ = nullptr; + ringBrightAlphaUniform_ = nullptr; + ringDarkAlphaUniform_ = nullptr; +} + +void ConeWave::Rebuild() { + // 清除当前几何体和uniform + Clear(); + + CreateRadarScanWave(); +} + +void ConeWave::CreateConeGeometry() { + // 创建锥形几何体 + osg::ref_ptr coneGeometry = new osg::Geometry(); + + // 锥形参数 + const int segments = 64; // 圆周细分数 + const float angleStep = 2.0f * osg::PI / segments; + + // 创建顶点数组 + osg::ref_ptr vertices = new osg::Vec3Array(); + osg::ref_ptr normals = new osg::Vec3Array(); + osg::ref_ptr texCoords = new osg::Vec2Array(); + + // 锥顶(位于原点) + vertices->push_back(osg::Vec3(0.0f, 0.0f, 0.0f)); + normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f)); + texCoords->push_back(osg::Vec2(0.5f, 0.5f)); + + // 底面圆周顶点(位于height_高度处) + for (int i = 0; i <= segments; ++i) { + float angle = i * angleStep; + float x = radius_ * cos(angle); + float y = radius_ * sin(angle); + float z = height_; - // 强制更新ShapeDrawable以应用颜色变化 - coneDrawable_->dirtyDisplayList(); + vertices->push_back(osg::Vec3(x, y, z)); + + // 计算法线(从锥顶指向圆周的单位向量) + osg::Vec3 normal(x, y, radius_); + normal.normalize(); + normals->push_back(normal); + + // 纹理坐标 + texCoords->push_back(osg::Vec2((x/radius_ + 1.0f) * 0.5f, (y/radius_ + 1.0f) * 0.5f)); + } + + coneGeometry->setVertexArray(vertices); + coneGeometry->setNormalArray(normals); + coneGeometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + coneGeometry->setTexCoordArray(0, texCoords); + + // 创建三角形索引 + osg::ref_ptr indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES); + + // 生成锥面三角形 + for (int i = 0; i < segments; ++i) { + // 每个三角形:锥顶 -> 底面点i -> 底面点i+1 + indices->push_back(0); // 锥顶 + indices->push_back(i + 1); // 底面点i + indices->push_back(i + 2); // 底面点i+1 + } + + coneGeometry->addPrimitiveSet(indices); + if (coneGeometry_.valid() && coneGeometry_->getNumParents() > 0) { + removeDrawable(coneGeometry_); + coneGeometry_ = coneGeometry; + coneDrawable_ = coneGeometry_.get(); + waveTimeUniform_ = nullptr; + levelHeightUniform_ = nullptr; + addDrawable(coneDrawable_); + } else { + coneGeometry_ = coneGeometry; + coneDrawable_ = coneGeometry_.get(); } } void ConeWave::CreateRadarScanWave() { - // 使用OSG内置的Cone几何体来创建雷达扫描区域 - // 创建锥形,锥形顶点在原点,开口向下(负Z方向) - cone_ = new osg::Cone(osg::Vec3(0, 0, -height_/2), radius_, height_); - - // 设置细分参数,创建开口锥形 - osg::TessellationHints* tesselate = new osg::TessellationHints; - tesselate->setCreateBottom(false); // 不创建底面,保持开口 - tesselate->setCreateTop(false); // 不创建顶面 - tesselate->setCreateBackFace(false); // 不创建背面 - tesselate->setDetailRatio(2.0f); // 增加细分精度 - - // 创建可绘制对象 - coneDrawable_ = new osg::ShapeDrawable(cone_, tesselate); - coneDrawable_->setColor(osg::Vec4(0.0f, 0.8f, 1.0f, coneAlpha_)); // 使用coneAlpha_设置基础颜色 + // 手动创建锥形几何体 + CreateConeGeometry(); // 添加到几何节点 addDrawable(coneDrawable_); @@ -286,7 +317,9 @@ void ConeWave::CreateRadarScanWave() { CreateRadarShader(); // 添加时间更新回调 - setUpdateCallback(new RadarWaveTimeCallback(waveTimeUniform_)); + osg::ref_ptr waveTimeCallback = new RadarWaveTimeCallback(waveTimeUniform_); + coneCallback_ = waveTimeCallback; + setUpdateCallback(coneCallback_); } void ConeWave::CreateRadarShader() { diff --git a/src/effects/ConeWave.h b/src/effects/ConeWave.h index 23b5e17e..6cf913be 100644 --- a/src/effects/ConeWave.h +++ b/src/effects/ConeWave.h @@ -22,6 +22,7 @@ public: // 雷达扫描波效果相关方法 void CreateRadarScanWave(); + void CreateConeGeometry(); void CreateRadarShader(); void SetWaveRadius(float radius); float GetWaveRadius() const { return waveRadius_; } @@ -55,9 +56,15 @@ public: void SetConeAlpha(float alpha); float GetConeAlpha() const { return coneAlpha_; } +protected: + void Clear(); + void Rebuild(); + + private: - osg::ref_ptr cone_; - osg::ref_ptr coneDrawable_; + osg::ref_ptr coneGeometry_; + osg::ref_ptr coneDrawable_; + osg::ref_ptr coneCallback_; float height_{ 6.0f }; float radius_{ 10.0f }; diff --git a/src/entities/ConeWaveComponent.cpp b/src/entities/ConeWaveComponent.cpp index 426fd343..ea522ced 100644 --- a/src/entities/ConeWaveComponent.cpp +++ b/src/entities/ConeWaveComponent.cpp @@ -112,10 +112,6 @@ void ConeWaveComponent::AddToRender() { void ConeWaveComponent::Initialize() { mt_ = new osg::MatrixTransform; - // 创建旋转矩阵,让锥形向下发射(绕X轴旋转180度) - // osg::Matrix rotationMatrix = osg::Matrix::rotate(osg::PI, osg::Vec3(1, 0, 0)); - // mt_->setMatrix(rotationMatrix); - mt_->addChild(coneWave_); }