DYTSrouce/src/effects/ConeWave.cpp

363 lines
12 KiB
C++
Raw Normal View History

2025-01-04 04:12:51 +00:00
#include "effects/ConeWave.h"
2025-06-19 14:05:52 +00:00
2025-01-04 04:12:51 +00:00
#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>
2025-06-24 15:40:11 +00:00
#include <osg/Cullface>
#include <osgEarth/Registry>
2025-01-04 04:12:51 +00:00
2025-02-22 15:16:54 +00:00
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;
};
2025-06-22 17:49:35 +00:00
// 雷达扫描波时间更新回调
class RadarWaveTimeCallback : public osg::NodeCallback {
public:
RadarWaveTimeCallback(osg::ref_ptr<osg::Uniform> 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<float>(currentTime - startTime_);
// 更新waveTime uniform
if (waveTimeUniform_.valid()) {
waveTimeUniform_->set(elapsedTime);
}
}
// 继续遍历场景图
traverse(node, nv);
}
private:
osg::ref_ptr<osg::Uniform> waveTimeUniform_;
double startTime_;
};
2025-01-04 04:12:51 +00:00
ConeWave::ConeWave() {
osgEarth::Registry::shaderGenerator().run(this);
2025-06-22 17:49:35 +00:00
currentTime_ = 0.0;
2025-06-23 23:47:18 +00:00
// 确保成员变量有合理的默认值
2025-06-25 00:10:01 +00:00
height_ = 1000.0f;
2025-06-23 23:47:18 +00:00
radius_ = 50.0f;
waveRadius_ = 100.0f;
waveSpeed_ = 20.0f;
waveCount_ = 3;
baseColor_ = osg::Vec4(0.0f, 0.8f, 1.0f, 1.0f);
waveColor_ = osg::Vec4(1.0f, 0.5f, 1.0f, 0.8f);
2025-06-24 15:40:11 +00:00
// 初始化透明度值
ringBrightAlpha_ = 0.8f;
ringDarkAlpha_ = 0.3f;
coneAlpha_ = 0.7f;
2025-01-04 04:12:51 +00:00
}
ConeWave::~ConeWave(void)
{
}
void ConeWave::Render(double dt) {
2025-06-22 17:49:35 +00:00
// 时间更新现在由RadarWaveTimeCallback回调处理
// 这里可以处理其他需要更新的属性
2025-01-04 04:12:51 +00:00
}
void ConeWave::InitGeode() {
2025-06-22 17:49:35 +00:00
CreateRadarScanWave();
2025-06-19 23:57:30 +00:00
getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
2025-06-22 17:49:35 +00:00
getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
2025-06-24 15:40:11 +00:00
setCullingActive(true);
2025-01-04 04:12:51 +00:00
}
void ConeWave::Destory() {
OnDestroy();
}
void ConeWave::SetHeight(float height) {
height_ = height;
2025-06-25 16:13:22 +00:00
if (cone_.valid()) {
2025-01-04 04:12:51 +00:00
cone_->setHeight(height_);
2025-06-25 16:13:22 +00:00
// 强制更新ShapeDrawable
if (coneDrawable_.valid()) {
coneDrawable_->dirtyDisplayList();
coneDrawable_->dirtyBound();
}
2025-01-04 04:12:51 +00:00
}
2025-06-25 16:13:22 +00:00
// 确保着色器已经初始化
if (!levelHeightUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
// 更新着色器中的高度uniform
if (levelHeightUniform_.valid()) {
levelHeightUniform_->set(height_ > 0 ? height_ : 100.0f);
2025-01-04 04:12:51 +00:00
}
}
void ConeWave::SetBaseColor(const osg::Vec4& color) {
baseColor_ = color;
2025-06-25 16:13:22 +00:00
// 确保着色器已经初始化
if (!baseColorUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (baseColorUniform_.valid()) {
baseColorUniform_->set(baseColor_);
}
2025-01-04 04:12:51 +00:00
}
2025-06-25 16:13:22 +00:00
void ConeWave::SetWaveCount(int count) {
waveCount_ = count;
// 确保着色器已经初始化
if (!waveCountUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (waveCountUniform_.valid()) {
waveCountUniform_->set(static_cast<float>(waveCount_));
}
}
void ConeWave::SetWaveSpeed(float speed) {
waveSpeed_ = speed;
// 确保着色器已经初始化
if (!waveSpeedUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
if (waveSpeedUniform_.valid()) {
waveSpeedUniform_->set(waveSpeed_);
}
}
2025-01-04 04:12:51 +00:00
2025-06-22 17:49:35 +00:00
// 雷达扫描波效果相关方法实现
void ConeWave::SetWaveRadius(float radius) {
waveRadius_ = radius;
2025-06-25 16:13:22 +00:00
// 确保着色器已经初始化
if (!waveRadiusUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
2025-06-22 17:49:35 +00:00
if (waveRadiusUniform_.valid()) {
waveRadiusUniform_->set(radius);
}
// 更新Cone的半径以匹配扫描波半径
if (cone_.valid()) {
cone_->setRadius(radius);
// 强制更新ShapeDrawable
if (coneDrawable_.valid()) {
coneDrawable_->dirtyDisplayList();
coneDrawable_->dirtyBound();
2025-02-22 15:16:54 +00:00
}
}
2025-06-22 17:49:35 +00:00
}
2025-02-22 15:16:54 +00:00
2025-06-22 17:49:35 +00:00
void ConeWave::SetWaveColor(const osg::Vec4& color) {
waveColor_ = color;
2025-06-25 16:13:22 +00:00
// 确保着色器已经初始化
if (!waveColorUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
2025-06-22 17:49:35 +00:00
if (waveColorUniform_.valid()) {
2025-06-25 16:13:22 +00:00
waveColorUniform_->set(waveColor_);
2025-06-22 17:49:35 +00:00
}
}
2025-02-22 15:16:54 +00:00
2025-06-24 15:40:11 +00:00
// 透明度控制方法实现
void ConeWave::SetRingBrightAlpha(float alpha) {
ringBrightAlpha_ = alpha;
2025-06-25 16:13:22 +00:00
// 确保着色器已经初始化
if (!ringBrightAlphaUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
2025-06-24 15:40:11 +00:00
if (ringBrightAlphaUniform_.valid()) {
ringBrightAlphaUniform_->set(alpha);
}
}
void ConeWave::SetRingDarkAlpha(float alpha) {
ringDarkAlpha_ = alpha;
2025-06-25 16:13:22 +00:00
// 确保着色器已经初始化
if (!ringDarkAlphaUniform_.valid() && coneDrawable_.valid()) {
CreateRadarShader();
}
2025-06-24 15:40:11 +00:00
if (ringDarkAlphaUniform_.valid()) {
ringDarkAlphaUniform_->set(alpha);
}
}
void ConeWave::SetConeAlpha(float alpha) {
coneAlpha_ = alpha;
// 更新锥形的基础颜色透明度
if (coneDrawable_.valid()) {
osg::Vec4 currentColor = coneDrawable_->getColor();
currentColor.a() = alpha;
coneDrawable_->setColor(currentColor);
2025-06-25 16:13:22 +00:00
// 强制更新ShapeDrawable以应用颜色变化
coneDrawable_->dirtyDisplayList();
2025-06-24 15:40:11 +00:00
}
}
2025-06-22 17:49:35 +00:00
void ConeWave::CreateRadarScanWave() {
// 使用OSG内置的Cone几何体来创建雷达扫描区域
2025-06-25 00:10:01 +00:00
cone_ = new osg::Cone(osg::Vec3(0, 0, 0), radius_, height_);
2025-06-22 17:49:35 +00:00
2025-06-25 00:10:01 +00:00
// 设置细分参数,创建开口锥形
2025-06-22 17:49:35 +00:00
osg::TessellationHints* tesselate = new osg::TessellationHints;
2025-06-25 00:10:01 +00:00
tesselate->setCreateBottom(false); // 不创建底面,保持开口
tesselate->setCreateTop(false); // 不创建顶面
2025-06-22 17:49:35 +00:00
tesselate->setCreateBackFace(false); // 不创建背面
tesselate->setDetailRatio(2.0f); // 增加细分精度
// 创建可绘制对象
coneDrawable_ = new osg::ShapeDrawable(cone_, tesselate);
2025-06-24 15:40:11 +00:00
coneDrawable_->setColor(osg::Vec4(0.0f, 0.8f, 1.0f, coneAlpha_)); // 使用coneAlpha_设置基础颜色
2025-06-22 17:49:35 +00:00
// 添加到几何节点
addDrawable(coneDrawable_);
// 设置渲染状态
osg::StateSet* ss = coneDrawable_->getOrCreateStateSet();
ss->setRenderBinDetails(120, "RenderBin");
2025-06-23 23:47:18 +00:00
ss->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); // 关闭面剔除以确保可见
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
2025-06-22 17:49:35 +00:00
// 设置混合模式
2025-06-23 23:47:18 +00:00
osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
2025-06-22 17:49:35 +00:00
ss->setAttributeAndModes(bf, osg::StateAttribute::ON);
ss->setMode(GL_BLEND, osg::StateAttribute::ON);
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
2025-06-24 15:40:11 +00:00
ss->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
2025-06-22 17:49:35 +00:00
// 创建雷达扫描波着色器
CreateRadarShader();
// 添加时间更新回调
setUpdateCallback(new RadarWaveTimeCallback(waveTimeUniform_));
}
2025-01-04 04:12:51 +00:00
2025-06-22 17:49:35 +00:00
void ConeWave::CreateRadarShader() {
2025-06-25 16:13:22 +00:00
// 防止重复创建着色器
if (waveTimeUniform_.valid()) {
return;
}
2025-06-22 17:49:35 +00:00
// 顶点着色器 - 使用简单的基于高度的条纹效果
static const char* vertexShaderSource =
2025-01-04 04:12:51 +00:00
"varying vec3 pos;\n"
"void main()\n"
"{\n"
2025-06-22 17:49:35 +00:00
" 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";
2025-06-24 15:40:11 +00:00
// 片段着色器 - 可控透明度的同心圆波纹效果
2025-06-22 17:49:35 +00:00
static const char* fragmentShaderSource =
"uniform float height;\n"
"uniform vec4 baseColor;\n"
2025-06-25 00:10:01 +00:00
"uniform vec4 waveColor;\n"
2025-06-22 17:49:35 +00:00
"uniform float waveTime;\n"
2025-06-24 15:40:11 +00:00
"uniform float ringBrightAlpha;\n"
"uniform float ringDarkAlpha;\n"
2025-06-25 00:10:01 +00:00
"uniform float waveSpeed;\n"
2025-06-22 17:49:35 +00:00
"varying vec3 pos;\n"
"void main()\n"
"{\n"
2025-06-23 23:47:18 +00:00
" float h = abs(pos.z) / max(height, 1.0);\n"
" float radialDist = sqrt(pos.x * pos.x + pos.y * pos.y);\n"
2025-06-25 00:10:01 +00:00
" float wavePhase = radialDist * 3.2 - waveTime * waveSpeed;\n"
2025-06-23 23:47:18 +00:00
" float ripple = sin(wavePhase);\n"
2025-06-24 15:40:11 +00:00
" if (ripple > 0.3)\n"
2025-06-22 17:49:35 +00:00
" {\n"
2025-06-25 00:10:01 +00:00
" gl_FragColor = vec4(waveColor.rgb, ringBrightAlpha);\n"
2025-06-22 17:49:35 +00:00
" }\n"
" else\n"
" {\n"
2025-06-24 15:40:11 +00:00
" gl_FragColor = vec4(baseColor.rgb, ringDarkAlpha);\n"
2025-06-22 17:49:35 +00:00
" }\n"
"}\n";
2025-06-25 00:10:01 +00:00
2025-06-22 17:49:35 +00:00
// 创建着色器
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
osg::ref_ptr<osg::Program> 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);
2025-06-25 00:10:01 +00:00
baseColorUniform_ = new osg::Uniform("baseColor", baseColor_); // 绿色雷达色调
2025-06-23 23:47:18 +00:00
waveColorUniform_ = new osg::Uniform("waveColor", waveColor_);
levelHeightUniform_ = new osg::Uniform("height", height_ > 0 ? height_ : 100.0f); // 确保高度不为0
2025-06-25 00:10:01 +00:00
waveSpeedUniform_ = new osg::Uniform("waveSpeed", waveSpeed_ > 0 ? waveSpeed_ : 1.0f);
2025-06-22 17:49:35 +00:00
2025-06-24 15:40:11 +00:00
// 创建透明度控制uniform变量
ringBrightAlphaUniform_ = new osg::Uniform("ringBrightAlpha", ringBrightAlpha_);
ringDarkAlphaUniform_ = new osg::Uniform("ringDarkAlpha", ringDarkAlpha_);
2025-06-22 17:49:35 +00:00
stateSet->addUniform(waveTimeUniform_);
stateSet->addUniform(baseColorUniform_);
2025-06-24 15:40:11 +00:00
stateSet->addUniform(waveColorUniform_);
2025-06-22 17:49:35 +00:00
stateSet->addUniform(levelHeightUniform_);
2025-06-25 00:10:01 +00:00
stateSet->addUniform(waveSpeedUniform_);
2025-06-24 15:40:11 +00:00
stateSet->addUniform(ringBrightAlphaUniform_);
stateSet->addUniform(ringDarkAlphaUniform_);
2025-06-22 17:49:35 +00:00
}