osg3.6绘制半球体

 

 

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/BlendFunc>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <cmath> //// 辅助函数:创建一个半球的 Geometry
osg::Geometry* createHemisphereGeometry(float radius = 1.0f, int slices = 30, int stacks = 15)
{
    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3Array* vertices = new osg::Vec3Array;
    osg::Vec3Array* normals = new osg::Vec3Array;
    osg::Vec4Array* colors = new osg::Vec4Array;

    // 1. 生成顶点和法线
    // 注意:半球的垂直角度范围是 0 到 PI/2 (90度)
    for (int i = 0; i <= stacks; i++)
    {
        float V = (float)i / (float)stacks; // 0 -> 1
        float phi = V * 3.1415926 * 0.5f; // 0 -> PI/2 (半球)

        for (int j = 0; j <= slices; j++)
        {
            float U = (float)j / (float)slices; // 0 -> 1
            float theta = U * 3.1415926 * 2.0f; // 0 -> 2PI

            // 计算球面坐标
            float x = radius * cos(theta) * sin(phi);
            float y = radius * sin(theta) * sin(phi);
            float z = radius * cos(phi); // 当 phi=0 时,z=radius (球顶); phi=PI/2 时,z=0 (赤道)

            vertices->push_back(osg::Vec3(x, y, z));

            // 球体的法线就是顶点坐标归一化后的方向(对于单位球,顶点坐标就是法线)
            normals->push_back(osg::Vec3(x, y, z) / radius);
        }
    }

    // 2. 构建索引 (Triangle Strips)
    for (int i = 0; i < stacks; i++)
    {
        osg::DrawElementsUInt* strip = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP);

        int baseIndex = i * (slices + 1);

        for (int j = 0; j <= slices; j++)
        {
            // 下层顶点
            strip->push_back(baseIndex + j);
            // 上层顶点
            strip->push_back(baseIndex + j + slices + 1);
        }
        geom->addPrimitiveSet(strip);
    }

    // 3. 设置数据
    geom->setVertexArray(vertices);
    geom->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
    // 设置红色半透明颜色
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 0.15f));
    geom->setColorArray(colors, osg::Array::BIND_OVERALL);

    return geom;
}

int main()
{
    // 1. 创建 Geode
    osg::ref_ptr<osg::Geode> geode = new osg::Geode();

    // 2. 添加半球
    osg::Geometry* hemisphere = createHemisphereGeometry(2.0f, 30, 15);
    geode->addDrawable(hemisphere);

    // 3. 开启混合实现半透明
    osg::StateSet* ss = geode->getOrCreateStateSet();
    ss->setMode(GL_BLEND, osg::StateAttribute::ON);
    ss->setAttribute(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));

    // 4. 运行
    osgViewer::Viewer viewer;
    viewer.setSceneData(geode);
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    return viewer.run();
}

 

a579d2179a0e8aae6f81701c7968ee01

 

 

######################

posted @ 2026-03-31 20:50  西北逍遥  阅读(2)  评论(0)    收藏  举报