查看: 1588|回复: 2

osgearth 体绘制之面片方法

[复制链接]
  • TA的每日心情
    开心
    2020-3-20 17:50
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2020-6-1 11:08:21 | 显示全部楼层 |阅读模式
    体数据 : 不好用点线面表达的大范围采样数据。
    面片方式渲染体数据 :
    优点:可以在任意性能的机器和平台上进行高速渲染
    缺点:对其做复杂的运算和效果相对低效
    代码说明:
    1、使用Geometry建立切片,设置好3D纹理坐标是关键。
    2、将Raw读取到3D纹理当中
    3、渲染即可


    #include <osgViewer/viewer>
    #include <osgDB/ReadFile>
    #include <osg/Texture3D>
    #include <osgDB/FileUtils>

    #ifdef _DEBUG
    #pragma comment(lib, "osgViewerd.lib")
    #pragma comment(lib, "osgDBd.lib")
    #pragma comment(lib, "osgd.lib")
    #else
    #pragma comment(lib, "osgViewer.lib")
    #pragma comment(lib, "osgDB.lib")
    #pragma comment(lib, "osg.lib")
    #endif

    #define VSIZE 128
    //从raw文件中创建3D纹理
    osg::Texture3D* Create3DTextureFromRaw()
    {
        osg::Texture3D* t3d = new osg::Texture3D;
        osg::Image* image = new osg::Image;
        image->allocateImage(VSIZE, VSIZE, VSIZE, GL_RGBA, GL_UNSIGNED_BYTE);
        t3d->setImage(image);

        osgDB::ifstream fin("buckball.raw", osgDB::ifstream::binary);

        for (int s = 0; s < VSIZE; s++)
        {
            for (int t = 0; t < VSIZE; t++)
            {
                for (int r = 0; r < VSIZE; r++)
                {
                    unsigned char* datePtr = image->data(s, t, r);
                    unsigned char dataTemp;
                    fin.read((char*)(&dataTemp), 1);
                    datePtr[0] = dataTemp;
                    datePtr[1] = 0;
                    datePtr[2] = 0;
                    if (dataTemp < 100)
                    {
                        dataTemp = 0;
                    }
                    datePtr[3] = dataTemp;

                }
            }
        }

        fin.close();

        t3d->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
        t3d->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
        t3d->setWrap(osg::Texture::WRAP_R, osg::Texture3D::CLAMP_TO_EDGE);
        t3d->setWrap(osg::Texture::WRAP_T, osg::Texture3D::CLAMP_TO_EDGE);
        t3d->setWrap(osg::Texture::WRAP_S, osg::Texture3D::CLAMP_TO_EDGE);

        return t3d;
    }

    //创建切片
    osg::Node* CreateCube()
    {
        osg::Geode* gnode = new osg::Geode;
        osg::Geometry* geom = new osg::Geometry;
        gnode->addDrawable(geom);

        osg::Vec3Array* vertex = new osg::Vec3Array;
        osg::Vec3Array* texCoord = new osg::Vec3Array;
        geom->setVertexArray(vertex);
        geom->setTexCoordArray(0, texCoord);

        //
        for (int y = VSIZE - 1; y >= 0; y--)
        {
            //压入顶点
            vertex->push_back(osg::Vec3f(-0.5, y*1.0 / VSIZE,-0.5));
            vertex->push_back(osg::Vec3f(-0.5, y*1.0 / VSIZE, 0.5));
            vertex->push_back(osg::Vec3f(0.5, y*1.0 / VSIZE, 0.5));
            vertex->push_back(osg::Vec3f(0.5, y*1.0 / VSIZE, -0.5));

            texCoord->push_back(osg::Vec3f(0.0, y*1.0 / VSIZE, 0.0));
            texCoord->push_back(osg::Vec3f(0.0, y*1.0 / VSIZE, 1.0));
            texCoord->push_back(osg::Vec3f(1.0, y*1.0 / VSIZE, 1.0));
            texCoord->push_back(osg::Vec3f(1.0, y*1.0 / VSIZE, 0.0));
        }

        geom->addPrimitiveSet(new osg:rawArrays(GL_QUADS, 0, vertex->size()));

        osg::StateSet* ss = gnode->getOrCreateStateSet();
        ss->setTextureAttributeAndModes(0, Create3DTextureFromRaw(), osg::StateAttribute::ON);
        ss->setMode(GL_BLEND, osg::StateAttribute::ON);
        ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

        return gnode;
    }

    int main()
    {
        osgViewer::Viewer viewer;
        viewer.setSceneData(CreateCube());
        return viewer.run();
    }
  • TA的每日心情
    开心
    2020-3-20 17:50
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2020-6-1 15:17:13 | 显示全部楼层
    本帖最后由 liyihongcug 于 2020-6-1 15:22 编辑

    配色
    billboard解决切片一拖角度就改变的问题
    实时的生成纹理坐标
    osg::TexGen::Mode::EYE_LINEAR
    公式:coordTex=p1’xe+p2’ye+p3’ze+p4’we
    其中(p1’,p2’,p3’,p4’)=(p1,p2,p3,p4)M-1
    pn是设置的参数
    clipNode解决冗余数据问题

    #include <osgViewer/viewer>
    #include <osgDB/ReadFile>
    #include <osg/Texture3D>
    #include <osgDB/FileUtils>
    #include <osg/Billboard>
    #include <osg/TexGenNode>
    #include <osg/ClipNode>


    #ifdef _DEBUG
    #pragma comment(lib, "osgViewerd.lib")
    #pragma comment(lib, "osgDBd.lib")
    #pragma comment(lib, "osgd.lib")
    #else
    #pragma comment(lib, "osgViewer.lib")
    #pragma comment(lib, "osgDB.lib")
    #pragma comment(lib, "osg.lib")
    #endif

    #define VSIZE 128
    //从raw文件中创建3D纹理
    osg::Texture3D* Create3DTextureFromRaw()
    {
        osg::Texture3D* t3d = new osg::Texture3D;
        osg::Image* image = new osg::Image;
        image->allocateImage(VSIZE, VSIZE, VSIZE, GL_RGBA, GL_UNSIGNED_BYTE);
        t3d->setImage(image);

        osgDB::ifstream fin("buckball.raw", osgDB::ifstream::binary);

        for (int s = 0; s < VSIZE; s++)
        {
            for (int t = 0; t < VSIZE; t++)
            {
                for (int r = 0; r < VSIZE; r++)
                {
                    unsigned char* datePtr = image->data(s, t, r);
                    unsigned char dataTemp;
                    fin.read((char*)(&dataTemp), 1);

                    if (dataTemp < 10)
                    {
                        datePtr[0] = 0;
                        datePtr[1] = 255;
                        datePtr[2] = dataTemp;
                        datePtr[3] = 0;
                    }
                    else if (dataTemp < 30)
                    {
                        datePtr[0] = dataTemp;
                        datePtr[1] = 255;
                        datePtr[2] = dataTemp;
                        datePtr[3] = 10;
                    }
                    else if (dataTemp >= 150)
                    {
                        datePtr[0] = 255;
                        datePtr[1] = 255;
                        datePtr[2] = dataTemp;
                        datePtr[3] = 100;
                    }
                    else
                    {
                        datePtr[0] = 0;
                        datePtr[1] = 0;
                        datePtr[2] = 0;
                        datePtr[3] = 0;
                    }


                }
            }
        }

        fin.close();

        t3d->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
        t3d->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
        t3d->setWrap(osg::Texture::WRAP_R, osg::Texture3D::CLAMP_TO_EDGE);
        t3d->setWrap(osg::Texture::WRAP_T, osg::Texture3D::CLAMP_TO_EDGE);
        t3d->setWrap(osg::Texture::WRAP_S, osg::Texture3D::CLAMP_TO_EDGE);

        return t3d;
    }

    //创建切片
    osg::Node* CreateCube()
    {
        osg::Billboard* bd = new osg::Billboard;
        bd->setMode(osg::Billboard::Mode:OINT_ROT_WORLD);
       
       
        osg::Geometry* geom = new osg::Geometry;
        bd->addDrawable(geom);
        bd->setPosition(0, osg::Vec3(0.5, 0.5, 0.5));


        osg::Vec3Array* vertex = new osg::Vec3Array;
        geom->setVertexArray(vertex);

        //
        float scalef = 1.75;
        for (int y = VSIZE - 1; y >= 0; y--)
        {
            //压入顶点
            vertex->push_back(osg::Vec3f(-0.5, y*1.0 / (VSIZE-1)-0.5,-0.5)*scalef);
            vertex->push_back(osg::Vec3f(-0.5, y*1.0 / (VSIZE-1)-0.5, 0.5)*scalef);
            vertex->push_back(osg::Vec3f(0.5, y*1.0 / (VSIZE-1)-0.5, 0.5)*scalef);
            vertex->push_back(osg::Vec3f(0.5, y*1.0 / (VSIZE-1)-0.5, -0.5)*scalef);

        }

        geom->addPrimitiveSet(new osg:rawArrays(GL_QUADS, 0, vertex->size()));


        osg::TexGenNode* tn = new osg::TexGenNode();
        tn->addChild(bd);
        tn->setTextureUnit(0);
        tn->getTexGen()->setPlanesFromMatrix(osg::Matrix::identity());
        tn->getTexGen()->setMode(osg::TexGen::Mode::EYE_LINEAR);

        osg::StateSet* ss = tn->getOrCreateStateSet();
        ss->setTextureAttributeAndModes(0, Create3DTextureFromRaw(), osg::StateAttribute::ON);
        ss->setMode(GL_BLEND, osg::StateAttribute::ON);
        ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

        ss->setTextureMode(0, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
        ss->setTextureMode(0, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
        ss->setTextureMode(0, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);

        osg::ClipNode* cn = new osg::ClipNode;
        cn->addChild(tn);

        osg::Vec3d v000 = osg::Vec3d(0.0, 0.0, 0.0);
        osg::Vec3d v100 = osg::Vec3d(1.0, 0.0, 0.0);
        osg::Vec3d v010 = osg::Vec3d(0.0, 1.0, 0.0);
        osg::Vec3d v110 = osg::Vec3d(1.0, 1.0, 0.0);

        osg::Vec3d v001 = osg::Vec3d(0.0, 0.0, 1.0);
        osg::Vec3d v101 = osg::Vec3d(1.0, 0.0, 1.0);
        osg::Vec3d v011 = osg::Vec3d(0.0, 1.0, 1.0);
        osg::Vec3d v111 = osg::Vec3d(1.0, 1.0, 1.0);

        cn->addClipPlane(new osg::ClipPlane(0, osg::Plane(v000, v011, v001)));
        cn->addClipPlane(new osg::ClipPlane(1, osg::Plane(v100, v111, v110)));
        cn->addClipPlane(new osg::ClipPlane(2, osg::Plane(v000, v101, v100)));
        cn->addClipPlane(new osg::ClipPlane(3, osg::Plane(v110, v011, v010)));
        cn->addClipPlane(new osg::ClipPlane(4, osg::Plane(v000, v110, v010)));
        cn->addClipPlane(new osg::ClipPlane(5, osg::Plane(v001, v111, v101)));

        return cn;
    }

    int main()
    {
        osgViewer::Viewer viewer;
        viewer.setSceneData(CreateCube());
        return viewer.run();
    }
  • TA的每日心情
    开心
    2020-3-20 17:50
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2020-6-2 09:56:43 | 显示全部楼层
    目标是:视点可见的蓝色边框的显示颜色

    眼睛的位置cameraPos:在顶点着色器中通过
    gl_ModelViewMatrixInverse * vec4(0,0,0,1);获取

    fn:是顶点着色器中的顶点,也是纹理坐标值

    fn-cameraPos得到光线的方向direction

    以fn为为起点direction为方向,1/切片数量为为步进长度,判断纹理坐标是否在[0,1]范围内为判断光线是否在体内的条件

    1、将配色表表达成纹理传入GPU
    2、从原始体数据中查询到标量数据
    3、拿查到的标量数据到本色表中查询
    到最终颜色。


    1、体渲染清晰可见的轮廓是等值面
    2、当前点的梯度表示这个点沿方向的最大变化率,垂直于等值面
    3、根据梯度的定义来求标量场中的梯度

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    OSG中国官方论坛-有您OSG在中国才更好

    网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

    联系我们

    • 工作时间:09:00--18:00
    • 反馈邮箱:1315785073@qq.com
    快速回复 返回顶部 返回列表