osg学习-4《读取外部面数据并显示》

 定义了颜色数据结构用来存储rgb颜色,在网上找了从灰度值计算彩虹色rgb值的方法,然后读取外部文件,根据面数据的值渲染颜色。其中IModelD是自定义的模板类,可以读写矩形网格系统下的面数据,获取面数据每个节点的坐标。

效果如下

 

#include <iostream>
#include <string>

#ifdef _WIN32
#include <windows.h>
#endif

#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

#include <EclipseModel/IModel2D.h>
using namespace EclipseModel;
osg::Vec3d v;

struct ColorRGBA {
    osg::Vec4f rgba;

    ColorRGBA(){
        rgba[0] = 1.0;
        rgba[1] = 1.0;
        rgba[2] = 1.0;
        rgba[3] = 1.0;
    }
    ColorRGBA(int R, int G, int B, int A = 255) {
        rgba[0] = (float)R/255;
        rgba[1] = (float)G/255;
        rgba[2] = (float)B/255;
        rgba[3] = (float)A/255;
    }
    ColorRGBA(float R, float G, float B, float A = 1.0f) {
        rgba[0] = R;
        rgba[1] = G;
        rgba[2] = B;
        rgba[3] = A;
    }
};


/// <summary>
/// 对应转换规则如下:
///    R     G    B    gray
/// 红 255,  0,   0,   255
/// 橙 255,  127, 0,   204
/// 黄 255,  255, 0,   153
/// 绿 0,    255, 0,   102
/// 青 0,    255, 255, 51
/// 蓝 0,    0,   255, 0
/// </summary>
/// <param name="value"></param>
/// <param name="vMin"></param>
/// <param name="vMax"></param>
/// <returns></returns>
ColorRGBA value2RGB(float value, float vMin, float vMax) {
    unsigned char r, g, b;
    unsigned char temp = (value - vMin) / (vMax - vMin) * 255;
    if (0 <= temp && temp <= 51)
    {
        b = 255;  //B
        g = 5 * temp;   //G
        r = 0;  //R
    }
    else if (temp <= 102)
    {
        temp -= 51;
        b = 255 - temp * 5;//B
        g = 255;//G
        r = 0;//R
    }
    else if (temp <= 153)
    {
        temp -= 102;
        b = 0;//B
        g = 255;//G
        r = 5 * temp;//R
    }
    else if (temp <= 204)
    {
        temp -= 153;
        b = 0;//B
        g = 255 - (temp * 128.0f) / 51.0;//G
        r = 255;//R
    }
    else {
        temp -= 204;
        b = 0;
        g = 127 - (temp * 128.0 / 51.0);
        r = 255;
    }
    return ColorRGBA(r, g, b);

}

osg::ref_ptr<osg::Node> readSurface(const std::string fileName) {
    IModel2D<float> surf;
    if (surf.readFromFile(fileName) < 0) {
        return nullptr;
    }

    //创建一个节点对象
    osg::ref_ptr<osg::Geode> geode = new osg::Geode();
    //创建一个集合对象
    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();

    int nj = surf.nj();
    int ni = surf.ni();
    
    //创建顶点数组
    osg::ref_ptr<osg::Vec3Array> vertx = new osg::Vec3Array();
    for (int j = 0; j <= nj; j++) {
        for (int i = 0; i <= ni; i++) {
            auto pos = surf.getNodePosFromIndex(i, j);
            int jj = j == nj ? nj - 1 : j;
            int ii = i == ni ? ni - 1 : i;
            float value = surf.getValue(jj, ii);
            vertx->push_back(osg::Vec3(pos.x, pos.y, value));
        }
    }

    float vmin = FLT_MAX;
    float vmax = -vmin;
    surf.getMinMax(vmin, vmax);

    //设置顶点数据
    geom->setVertexArray(vertx.get());
    //创建颜色数组
    osg::ref_ptr<osg::Vec4Array> vcolor = new osg::Vec4Array();

    for (int j = 0; j < nj; j++) {
        for (int i = 0; i < ni; i++) {
            int index = j * (ni + 1) + i;
            //创建四边形定点数组,指定绘图基元为四边形,注意添加顺序
            osg::ref_ptr<osg::DrawElementsUInt> quad =
                new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
            quad->push_back(index);
            quad->push_back(index + 1);
            quad->push_back(index + ni + 2);
            quad->push_back(index + ni + 1);

            //添加到几何体
            geom->addPrimitiveSet(quad.get());
            auto color = value2RGB(surf.getValue(j, i), vmin, vmax);
            vcolor->push_back(color.rgba);  //random color
        }
    }

    //设置颜色数组
    geom->setColorArray(vcolor.get());


    //设置颜色的绑定方式为单个顶点
    //geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
    geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);

    // 创建法线数组
    osg::ref_ptr<osg::Vec3Array>nc = new osg::Vec3Array();
    //添加法线
    nc->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));

    // 设置法线数组
    geom->setNormalArray(nc.get());
    //设置法线的绑定方式为全部顶点
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    //添加到叶节点
    geode->addDrawable(geom.get());

    return geode.get();
}

int main(int argc, char*argv[])
{
    std::cout << "it read a surface map and show" << std::endl;
    std::string fileName = argv[1];

    // 创建Viewer对象,场景浏览器创建一个节点。viewer->setSceneData(root.get())viewer->realize(viewer - un();
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

    //创建场最组节点
    osg::ref_ptr<osg::Group> root = new osg::Group();

    //读取面数据创建的节点模型
    osg::ref_ptr<osg::Node> node = readSurface(fileName);

    //添加到场景
    root->addChild(node.get());

    //优化场景数据
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());

    //设置场景数据
    viewer->setSceneData(root.get());

    //设置渲染的窗口
    //viewer->setUpViewAcrossAllScreens();  //default on all screens
    viewer->setUpViewOnSingleScreen(0);

    //开始渣染
    viewer->run();

    return 0;
}


 

posted @   Oliver2022  阅读(127)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示