5.osg中用顶点绘制球体并贴上地球纹理

代码及注释如下:


classGeometry_sphere : public osg::Geometry

{

public:

    Geometry_sphere(double dRadius=1, intiNumPartsLongtitude_half=13,

        int iNumPartsLatitude_half=13);

 

    void InitVertices();//初始化顶点

    void AddFaces();//添加面

 

protected:

    double m_dRadius;//半径

    int m_iNumPartsLongtitude_half;//使用经线数的一半

    int m_iNumPartsLatitude_half;//纬线数的总数加1的一半

   

    osg::ref_ptr<osg::Vec3Array>m_pVertices;//绘制顶点索引

    osg::ref_ptr<osg::Vec2Array>m_pIndex;//渲染顶点索引

};

 

 

         Geometry_sphere::Geometry_sphere(doubledRadius,int iNumPartsLongtitude_half,

    int iNumPartsLatitude_half)

    :m_dRadius(dRadius),

    m_iNumPartsLongtitude_half(iNumPartsLongtitude_half),

    m_iNumPartsLatitude_half(iNumPartsLatitude_half)

{

    InitVertices();

    AddFaces();

}

 

void Geometry_sphere::InitVertices()

{

    //构成球的顶点总数为 经线数加1 * 纬线总数加2(两极点)主要是为之后渲染的封闭性考虑

    m_pVertices = newosg::Vec3Array((m_iNumPartsLongtitude_half*2+1)*

        ((m_iNumPartsLatitude_half+1)*2-1));

    //渲染顶点索引数与绘制顶点数相同

    m_pIndex = new osg::Vec2Array((m_iNumPartsLongtitude_half*2+1)*

        ((m_iNumPartsLatitude_half+1)*2-1));

 

    double dDeltaHeight =m_dRadius/m_iNumPartsLatitude_half;//纬度间高度

    double dDeltaAngle =osg::PI/m_iNumPartsLongtitude_half;//经度间夹角

 

    double dAngle,dHeight=m_dRadius,dLatitudeRadius;//角度、高度、对应纬度上的半径

 

    //初始化所有点

//x、y用于渲染顶点索引

    float y =1.0/((float)m_iNumPartsLatitude_half*2);

    float x =1.0/((float)m_iNumPartsLongtitude_half*2);

    for(int i = 0; i <(m_iNumPartsLatitude_half)*2; ++i,dHeight-=dDeltaHeight)

    {

        dLatitudeRadius =sqrt(m_dRadius*m_dRadius-fabs(dHeight)*fabs(dHeight));

        dAngle = 0;

 

        for(int k = 0; k <m_iNumPartsLongtitude_half*2+1; ++k,dAngle+=dDeltaAngle)

        {

            if(((i*(m_iNumPartsLongtitude_half*2+1)+k)+1)%(m_iNumPartsLongtitude_half*2+1)==0)

            {

                (*m_pVertices)[i*(m_iNumPartsLongtitude_half*2+1)+k]=(*m_pVertices)[i*(m_iNumPartsLongtitude_half*2+1)+k-m_iNumPartsLongtitude_half*2];

                (*m_pIndex)[i*(m_iNumPartsLongtitude_half*2+1)+k].set(k*x,1-i*y);

            }

            else

            {

                (*m_pVertices)[i*(m_iNumPartsLongtitude_half*2+1)+k].set(

                    dLatitudeRadius*cos(dAngle),dLatitudeRadius*sin(dAngle),

                    dHeight);

                (*m_pIndex)[i*(m_iNumPartsLongtitude_half*2+1)+k].set(k*x,1-i*y);

            }

        }

    }

    //初始化最后一条经线上的点(该经线与第一条经线重合,绘制顶点值相同,但渲染顶点值不同)

    for(int i = 0; i <m_iNumPartsLongtitude_half*2+1; ++i)

    {

        if(i==m_iNumPartsLongtitude_half*2)

        {

            (*m_pVertices)[(m_iNumPartsLongtitude_half*2+1)*((m_iNumPartsLatitude_half+1)*2-2)+i].set(0,0,dHeight);

            (*m_pIndex)[(m_iNumPartsLongtitude_half*2+1)*((m_iNumPartsLatitude_half+1)*2-2)+i].set(i*x,0);

        }

        else

        {

            (*m_pVertices)[(m_iNumPartsLongtitude_half*2+1)*((m_iNumPartsLatitude_half+1)*2-2)+i].set(0,0,dHeight);

            (*m_pIndex)[(m_iNumPartsLongtitude_half*2+1)*((m_iNumPartsLatitude_half+1)*2-2)+i].set(i*x,0);

        }

    }

}

 

voidGeometry_sphere::AddFaces()

{

    //设置gemoetry对象索引

    this->setVertexArray(m_pVertices.get());

    this->setTexCoordArray(0,m_pIndex.get());

 

    int iNumLongtitude =m_iNumPartsLongtitude_half*2;

    int iNumLatitude =m_iNumPartsLatitude_half*2;

 

    for(int k = 0; k < iNumLatitude; ++k)

    {

        int i;

        for(i = 0; i < iNumLongtitude; ++i)

        {

            if(((iNumLongtitude+1)*k+i+1)%(m_iNumPartsLongtitude_half*2+1)!=0)

            {

                //采用四边形的绘制方法组成球的框架

                osg::ref_ptr<osg::DrawElementsUInt>pQuads= new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS,0);

 

                pQuads->push_back((iNumLongtitude+1)*k+i);

                pQuads->push_back((iNumLongtitude+1)*k+i+1);

                pQuads->push_back((iNumLongtitude+1)*k+i+1+(iNumLongtitude+1));

                pQuads->push_back((iNumLongtitude+1)*k+i+(iNumLongtitude+1));

               

                addPrimitiveSet(pQuads.get());

            }

        }

    }

 

    //优化该对象

    osgUtil::SmoothingVisitor smv;

    smv.smooth(*this);

    //设置各点法向量

    osg::ref_ptr<osg::Vec3Array>pNormals =new osg::Vec3Array();

    for(int i = 0; i <m_pVertices->size(); ++i)

    {

        osg::Vec3 pt = (*m_pVertices)[i];

        pt.normalize();

        pNormals->push_back(pt);

    }

    this->setNormalArray(pNormals);

    this->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);

    //设置各点颜色

    osg::ref_ptr<osg::Vec4Array>pColor =new osg::Vec4Array();

    for(int i = 0; i <m_pVertices->size(); ++i)

    {

        osg::Vec4 pt(1.0, 1.0, 1.0, 1.0);

        pColor->push_back(pt);

    }

    this->setColorArray(pColor);

    this->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值