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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」