五、QT+OSG可视化——加入纹理,加入回调实现动效

QTOSG_CVDCurveMWS_CallBack项目说明

1 项目介绍

该项目是“4”这篇博客的功能增加,加入了纹理,同时加入了节点回调,实现路径滚动,与平面动效 可视化代码也放入了GenerateDrawable类中,主函数中调用即可

该项目是QTOSG_CVDCurveMWS_CallBack其他主要功能参考上一篇博客

新增了平面动效和路径滚动动效。

2 GenerateDrawable类新增代码

这是所有自己手动在osg窗口添加可绘制体对象的类,都在这个类中写,主类调用就行(可视化代码不写在主类中了)

新增代码如下:

GenerateDrawable.h
#ifndef GENERATEDRAWABLE_H
 #define GENERATEDRAWABLE_H
 ​
 #include <osg/Group>
 #include <osg/Geode>
 #include <osg/PrimitiveSet>
 #include <osg/Geometry>
 #include <osg/LineWidth>
 ​
 #include <osg/Texture2D>
 #include <osgDB/ReadFile>
 #include <osg/Image>
 ​
 class GenerateDrawable
 {
 public:
     GenerateDrawable();
 ​
     osg::ref_ptr<osg::Geode> createCubeEdgeWireframe();
     osg::ref_ptr<osg::Geometry> createPathRotate(int numPoints);//创建滚动路径
 ​
     //创建纹理
     void createTexture2D(osg::StateSet& ss, std::string filename);
 };
 ​
 #endif // GENERATEDRAWABLE_H
 
GenerateDrawable.cpp
 
//颜色映射函数
 // 随机生成的属性值范围
 const float ATTRIBUTE_MIN = 0.0f;
 const float ATTRIBUTE_MAX = 500.0f;
 osg::Vec4 mapValueToColor(float value)
 {
     float normalized = (value - ATTRIBUTE_MIN) / (ATTRIBUTE_MAX - ATTRIBUTE_MIN);  // 将值归一化到 [0, 1]
 ​
     if (normalized <= 0.2f)  // 红到黄
         return osg::Vec4(1.0f, normalized / 0.2f, 0.0f, 1.0f);
     else if (normalized <= 0.4f)  // 黄到绿
         return osg::Vec4(1.0f - (normalized - 0.2f) / 0.2f, 1.0f, 0.0f, 1.0f);
     else if (normalized <= 0.6f)  // 绿到青
         return osg::Vec4(0.0f, 1.0f, (normalized - 0.4f) / 0.2f, 1.0f);
     else if (normalized <= 0.8f)  // 青到蓝
         return osg::Vec4(0.0f, 1.0f - (normalized - 0.6f) / 0.2f, 1.0f, 1.0f);
     else  // 蓝色
         return osg::Vec4(0.0f, 0.0f, 1.0f - (normalized - 0.8f) / 0.2f, 1.0f);
 }
 // 回调函数,用于沿X方向传递属性值并更新颜色——曲面渐变
 class TimedAttributeTransferCallback : public osg::Drawable::UpdateCallback {
 public:
     TimedAttributeTransferCallback(osg::Vec4Array* colors, int gridSize)
         : _colors(colors), _gridSize(gridSize),_flag(0){}
 ​
     virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable) override {
         _flag++;
         if(_flag%10!=0) {//控制变化快慢
             return;
         }
         // 根据属性值更新颜色
         osg::Vec4 temp = (*_colors)[0];
         for (int i = 0; i < _colors->size()-1; ++i) {
             (*_colors)[i] = (*_colors)[i+1];
         }
         (*_colors)[_colors->size()-1] = temp;
         _colors->dirty();
     }
 ​
 private:
     osg::ref_ptr<osg::Vec4Array> _colors;
     int _gridSize;
     int _flag;
 };
 osg::ref_ptr<osg::Geode> GenerateDrawable::createGradientPlane(int gridSize, std::vector<float> &attributeValues, osg::ref_ptr<osg::Vec4Array> colors)
 {
     osg::ref_ptr<osg::Geode> geode = new osg::Geode;
     osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
     osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
 ​
     geometry->setUseDisplayList(false);            // 禁用 Display List
     geometry->setUseVertexBufferObjects(true);     // 启用 VBO
 ​
     float size = 1.0f;
     float step = size / gridSize;
 ​
     // 创建平面上的点和颜色
     for (int i = 0; i <= gridSize; ++i)
     {
         for (int j = 0; j <= gridSize; ++j)
         {
             float x = -size / 2 + i * step;
             float y = -size / 2 + j * step;
             float z = 0.0f;
 ​
             vertices->push_back(osg::Vec3(x, y, z));
 ​
             // 为每个点生成一个随机属性值
             float attributeValue = ATTRIBUTE_MIN + static_cast<float>(rand()) / RAND_MAX * (ATTRIBUTE_MAX - ATTRIBUTE_MIN);
             attributeValues.push_back(attributeValue);  // 存储属性值
             colors->push_back(mapValueToColor(attributeValue));  // 将属性值映射到颜色
         }
     }
 ​
     // 创建平面上的矩形图元
     for (int i = 0; i < gridSize; ++i)
     {
         for (int j = 0; j < gridSize; ++j)
         {
             int idx0 = i * (gridSize + 1) + j;
             int idx1 = idx0 + 1;
             int idx2 = idx0 + (gridSize + 1);
             int idx3 = idx2 + 1;
 ​
             osg::ref_ptr<osg::DrawElementsUInt> quad = new osg::DrawElementsUInt(GL_QUADS);
             quad->push_back(idx0);
             quad->push_back(idx1);
             quad->push_back(idx3);
             quad->push_back(idx2);
 ​
             geometry->addPrimitiveSet(quad);
         }
     }
 ​
     geometry->setVertexArray(vertices);
     geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);  // 每个顶点有单独的颜色
     geometry->setUpdateCallback(new TimedAttributeTransferCallback(colors, gridSize));
     geode->addDrawable(geometry);
     return geode;
 }
 // 颜色渐变函数,根据时间参数生成颜色
 osg::Vec4 getDynamicColor(float t) {
     return osg::Vec4((std::sin(t) + 1.0f) / 2.0f, (std::cos(t) + 1.0f) / 2.0f, 0.5f, 1.0f);  // 从红到蓝的渐变
 }
 // 路径滚动回调
 class RotateLineCallback : public osg::Drawable::UpdateCallback
 {
 public:
     RotateLineCallback(osg::Vec3Array* vertices):_vertices(vertices), _flag(0){}
 ​
     virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable){
         _flag++;
         if(_flag%8!=0) return;
 ​
         osg::Geometry* geom = dynamic_cast<osg::Geometry*>(drawable);
         if(!geom) return;
         //qDebug()<<"kasihi";
         for(int i=0; i< _vertices->size()-1; i++){
             (*_vertices)[i]=(*_vertices)[i+1];
             //qDebug()<<(*_vertices)[i].x()<<","<<(*_vertices)[i].y()<<","<<(*_vertices)[i].z();
         }
         osg::Vec3 pt = _vertices->back();
         float x=pt.x()+0.05;
         float y=pt.y()+0.05;
         if(x>=0.5) x=-0.5;
         if(y>=0.5) y=-0.5;
         (*_vertices)[_vertices->size()-1]=osg::Vec3(x,y,0.0);
 ​
         _vertices->dirty();
         drawable->dirtyDisplayList();  // 强制重绘几何体
     }
 ​
 protected:
     osg::ref_ptr<osg::Vec3Array> _vertices;
     int _flag;
 };
 osg::ref_ptr<osg::Geometry> GenerateDrawable::createPathRotate(int numPoints)
 {
     osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
     osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
     osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
     std::vector<float> attributeValues;  // 存储每个点的属性值
 ​
     for (int i = 0; i < numPoints; ++i) {
         float t = static_cast<float>(i) * 0.01;
         float x = t - 0.2f;
         //float y = std::sin(3.14 * t) * 0.5f;  // 非直线路径
         float y = 0.0+i*0.01;
         float z = 0;
         vertices->push_back(osg::Vec3(x, y, z));
         //qDebug()<<"("<<x<<","<<y<<","<<z<<")";
         // 为每个点生成一个随机属性值
         float attributeValue = ATTRIBUTE_MIN + static_cast<float>(rand()) / RAND_MAX * (ATTRIBUTE_MAX - ATTRIBUTE_MIN);
         attributeValues.push_back(attributeValue);  // 存储属性值
         colors->push_back(getDynamicColor(attributeValue));
     }
 ​
     geometry->setVertexArray(vertices);
     geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
     geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, numPoints));  // 绘制路径
     geometry->setUpdateCallback(new RotateLineCallback(vertices));
 ​
     osg::ref_ptr<osg::LineWidth> lineWidth = new osg::LineWidth(4.5f); // 线宽
     geometry->getOrCreateStateSet()->setAttributeAndModes(lineWidth, osg::StateAttribute::ON);
     return geometry;
 }
 //生成纹理
 void GenerateDrawable::createTexture2D(osg::StateSet &ss, std::string filename)
 {
     osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
     texture->setImage(osgDB::readImageFile(filename));
     texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
     texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
     texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_BORDER);
     texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_BORDER);
     texture->setBorderColor(osg::Vec4(1.0,1.0,0.0,1.0));
 ​
     ss.setTextureAttributeAndModes(0,texture.get());
 }

3 主类调用-MainWindow类

主类——调用OSGWidget类添加osg窗口,同时调用GenerateDrawable类添加可视化对象

MainWindow.cpp
 
//路径滚动
 void MainWindow::on_pBO4_clicked()
 {
     //获取osg窗口对象
     std::map<std::string, int>::const_iterator it= osgToIndexMap.find("PlaneShow");
     int index = it->second;
     osg::ref_ptr<osg::Group> showGroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(0));
 ​
 ​
     //添加路径对象
     int numPoints = 10;
     osg::ref_ptr<osg::Geometry> pathGeometry = _generateDrawable->createPathRotate(numPoints);
     osg::ref_ptr<osg::Geode> pathGeode = new osg::Geode;
     pathGeode->addDrawable(pathGeometry);
     if (showGroup->getNumChildren() > 1) {
         // 第二个子节点的位置是 1
         showGroup->setChild(1, pathGeode);  // 替换为新节点 geo
     }
 ​
     //添加一个图片纹理
     osg::ref_ptr<osg::Geode> texture = new osg::Geode;
     texture->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-0.5,-0.5,0),osg::Vec3(1.0,0.0,0.0),
                                                           osg::Vec3(0.0,1.0,0.0),0.0,0.0,1.0,1.0));
     _generateDrawable->createTexture2D(*(texture->getOrCreateStateSet()),"E://TempFiles//test.png");
     showGroup->addChild(texture);
 }
 ​

4 效果图

5 最后

动图有些模糊,但是实现的思想如上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值