add rebuild cone wave

This commit is contained in:
brige 2025-06-27 08:29:36 +08:00
parent 1d7ba7c418
commit 09767ecdbd
3 changed files with 127 additions and 91 deletions

View File

@ -113,7 +113,7 @@ void ConeWave::Render(double dt) {
} }
void ConeWave::InitGeode() { void ConeWave::InitGeode() {
CreateRadarScanWave(); Rebuild();
getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
@ -127,32 +127,13 @@ void ConeWave::Destory() {
void ConeWave::SetHeight(float height) { void ConeWave::SetHeight(float height) {
height_ = height; height_ = height;
if (cone_.valid()) {
cone_->setHeight(height_); Rebuild();
// 更新锥形中心位置以保持顶点在原点
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);
}
} }
void ConeWave::SetBaseColor(const osg::Vec4& color) { void ConeWave::SetBaseColor(const osg::Vec4& color) {
baseColor_ = color; baseColor_ = color;
// 确保着色器已经初始化
if (!baseColorUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (baseColorUniform_.valid()) { if (baseColorUniform_.valid()) {
baseColorUniform_->set(baseColor_); baseColorUniform_->set(baseColor_);
} }
@ -160,22 +141,11 @@ void ConeWave::SetBaseColor(const osg::Vec4& color) {
void ConeWave::SetWaveCount(int count) { void ConeWave::SetWaveCount(int count) {
waveCount_ = count; waveCount_ = count;
// 确保着色器已经初始化 Rebuild();
if (!waveCountUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (waveCountUniform_.valid()) {
waveCountUniform_->set(static_cast<float>(waveCount_));
}
} }
void ConeWave::SetWaveSpeed(float speed) { void ConeWave::SetWaveSpeed(float speed) {
waveSpeed_ = speed; waveSpeed_ = speed;
// 确保着色器已经初始化
if (!waveSpeedUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (waveSpeedUniform_.valid()) { if (waveSpeedUniform_.valid()) {
waveSpeedUniform_->set(waveSpeed_); waveSpeedUniform_->set(waveSpeed_);
@ -185,30 +155,13 @@ void ConeWave::SetWaveSpeed(float speed) {
// 雷达扫描波效果相关方法实现 // 雷达扫描波效果相关方法实现
void ConeWave::SetWaveRadius(float radius) { void ConeWave::SetWaveRadius(float radius) {
waveRadius_ = radius; waveRadius_ = radius;
// 确保着色器已经初始化 radius_ = radius; // 同时更新锥形的半径
if (!waveRadiusUniform_.valid() && coneDrawable_.valid()) { Rebuild();
CreateRadarShader();
}
if (waveRadiusUniform_.valid()) {
waveRadiusUniform_->set(radius);
}
// 更新Cone的半径以匹配扫描波半径
if (cone_.valid()) {
cone_->setRadius(radius);
// 强制更新ShapeDrawable
if (coneDrawable_.valid()) {
coneDrawable_->dirtyDisplayList();
coneDrawable_->dirtyBound();
}
}
} }
void ConeWave::SetWaveColor(const osg::Vec4& color) { void ConeWave::SetWaveColor(const osg::Vec4& color) {
waveColor_ = color; waveColor_ = color;
// 确保着色器已经初始化
if (!waveColorUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (waveColorUniform_.valid()) { if (waveColorUniform_.valid()) {
waveColorUniform_->set(waveColor_); waveColorUniform_->set(waveColor_);
} }
@ -217,10 +170,7 @@ void ConeWave::SetWaveColor(const osg::Vec4& color) {
// 透明度控制方法实现 // 透明度控制方法实现
void ConeWave::SetRingBrightAlpha(float alpha) { void ConeWave::SetRingBrightAlpha(float alpha) {
ringBrightAlpha_ = alpha; ringBrightAlpha_ = alpha;
// 确保着色器已经初始化
if (!ringBrightAlphaUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (ringBrightAlphaUniform_.valid()) { if (ringBrightAlphaUniform_.valid()) {
ringBrightAlphaUniform_->set(alpha); ringBrightAlphaUniform_->set(alpha);
} }
@ -228,10 +178,6 @@ void ConeWave::SetRingBrightAlpha(float alpha) {
void ConeWave::SetRingDarkAlpha(float alpha) { void ConeWave::SetRingDarkAlpha(float alpha) {
ringDarkAlpha_ = alpha; ringDarkAlpha_ = alpha;
// 确保着色器已经初始化
if (!ringDarkAlphaUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (ringDarkAlphaUniform_.valid()) { if (ringDarkAlphaUniform_.valid()) {
ringDarkAlphaUniform_->set(alpha); ringDarkAlphaUniform_->set(alpha);
} }
@ -240,31 +186,116 @@ void ConeWave::SetRingDarkAlpha(float alpha) {
void ConeWave::SetConeAlpha(float alpha) { void ConeWave::SetConeAlpha(float alpha) {
coneAlpha_ = alpha; coneAlpha_ = alpha;
// 更新锥形的基础颜色透明度 // 更新锥形的基础颜色透明度
if (coneDrawable_.valid()) { if (coneGeometry_.valid()) {
osg::Vec4 currentColor = coneDrawable_->getColor(); // 通过着色器uniform来控制透明度而不是直接设置颜色
currentColor.a() = alpha; // 这里可以在CreateRadarShader中添加coneAlpha uniform来控制
coneDrawable_->setColor(currentColor); // 或者通过StateSet的材质属性来控制
osg::StateSet* ss = coneGeometry_->getOrCreateStateSet();
osg::ref_ptr<osg::Material> 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);
}
}
// 强制更新ShapeDrawable以应用颜色变化 void ConeWave::Clear() {
coneDrawable_->dirtyDisplayList(); // 清除锥形几何体和相关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<osg::Geometry> coneGeometry = new osg::Geometry();
// 锥形参数
const int segments = 64; // 圆周细分数
const float angleStep = 2.0f * osg::PI / segments;
// 创建顶点数组
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array();
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array();
osg::ref_ptr<osg::Vec2Array> 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_;
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<osg::DrawElementsUInt> 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() { void ConeWave::CreateRadarScanWave() {
// 使用OSG内置的Cone几何体来创建雷达扫描区域 // 手动创建锥形几何体
// 创建锥形锥形顶点在原点开口向下负Z方向 CreateConeGeometry();
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_设置基础颜色
// 添加到几何节点 // 添加到几何节点
addDrawable(coneDrawable_); addDrawable(coneDrawable_);
@ -286,7 +317,9 @@ void ConeWave::CreateRadarScanWave() {
CreateRadarShader(); CreateRadarShader();
// 添加时间更新回调 // 添加时间更新回调
setUpdateCallback(new RadarWaveTimeCallback(waveTimeUniform_)); osg::ref_ptr<osg::NodeCallback> waveTimeCallback = new RadarWaveTimeCallback(waveTimeUniform_);
coneCallback_ = waveTimeCallback;
setUpdateCallback(coneCallback_);
} }
void ConeWave::CreateRadarShader() { void ConeWave::CreateRadarShader() {

View File

@ -22,6 +22,7 @@ public:
// 雷达扫描波效果相关方法 // 雷达扫描波效果相关方法
void CreateRadarScanWave(); void CreateRadarScanWave();
void CreateConeGeometry();
void CreateRadarShader(); void CreateRadarShader();
void SetWaveRadius(float radius); void SetWaveRadius(float radius);
float GetWaveRadius() const { return waveRadius_; } float GetWaveRadius() const { return waveRadius_; }
@ -55,9 +56,15 @@ public:
void SetConeAlpha(float alpha); void SetConeAlpha(float alpha);
float GetConeAlpha() const { return coneAlpha_; } float GetConeAlpha() const { return coneAlpha_; }
protected:
void Clear();
void Rebuild();
private: private:
osg::ref_ptr<osg::Cone> cone_; osg::ref_ptr<osg::Geometry> coneGeometry_;
osg::ref_ptr<osg::ShapeDrawable> coneDrawable_; osg::ref_ptr<osg::Drawable> coneDrawable_;
osg::ref_ptr<osg::NodeCallback> coneCallback_;
float height_{ 6.0f }; float height_{ 6.0f };
float radius_{ 10.0f }; float radius_{ 10.0f };

View File

@ -112,10 +112,6 @@ void ConeWaveComponent::AddToRender() {
void ConeWaveComponent::Initialize() { void ConeWaveComponent::Initialize() {
mt_ = new osg::MatrixTransform; 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_); mt_->addChild(coneWave_);
} }