#include "effects/ConeWave.h" /* #include #include #include #include #include #include #include #include #include #include #include #include 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(node); if (geode) { osg::Geometry* geometry = dynamic_cast(geode->getDrawable(0)); if (geometry) { osg::Vec3Array* vertices = dynamic_cast(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 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); osg::ref_ptr fragmentShader = new osg::Shader(osg::Shader::FRAGMENT); fragmentShader->setShaderSource(fragSource); osg::StateSet* stateset = coneDrawable_->getOrCreateStateSet(); // osg::ref_ptr 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 blendFunc = new osg::BlendFunc(); // stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON); // osg::ref_ptr 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 #include #include #include #include #include #include #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 m_geode; osg::ref_ptr m_geom; osg::ref_ptr m_colorArray; osg::ref_ptr m_pointVector; osg::ref_ptr 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(node); if (mtCone != NULL) { osg::MatrixTransform* mtR = dynamic_cast(mtCone->getParent(0)); osg::MatrixTransform* mt = dynamic_cast(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 geode = new osg::Geode(); osg::ref_ptr geom = new osg::Geometry; osg::ref_ptr vertex = new osg::Vec3Array; osg::ref_ptr normal = new osg::Vec3Array; osg::ref_ptr drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLE_FAN); osg::ref_ptr 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 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 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(node->getChild(0)); // osg::MatrixTransform* mtS = dynamic_cast(mtR->getChild(0)); // mtR->addChild(mtCone); _waveBeamCone = mtCone; } void ConeWave::changeWaveBeamConeTarget(double latitude, double longitude, double height, bool ifDynamic) { WaveBeamConeCallBack* coneCallBack = dynamic_cast(_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(mtCone->getParent(0)); osg::MatrixTransform* mt = dynamic_cast(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(_waveBeamCone->getUpdateCallback()); if (coneCallBack != NULL) { coneCallBack->m_color = color; coneCallBack->m_lineColor = lineColor; coneCallBack->m_lineWidth = lineWidth; //创建材质对象 osg::ref_ptr 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); } } }