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 最后
动图有些模糊,但是实现的思想如上。