5.osg中用顶点绘制球体并贴上地球纹理
2015-07-16 20:13
393 查看
代码及注释如下:
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);
}
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);
}
相关文章推荐
- 关于 OGRE 与 OSG 的简略比较(转自www.MyException.Cn )
- Qt中GraphicsView/GraphicsScene加载osg时场景瞬移。。。
- osg如何画网格
- OSG学习——配置问题
- OSG嵌入到MFC中报内存泄露
- osgViewer销毁bug
- iOS 下编译 OSG 引擎
- [osg]源码分析:OSG中的智能指针osg::ref_ptr
- OSG中的相关词汇表
- 简单OSG小程序,实现在cmd下osgviewer <filename>小功能
- OSG 添加操作器及功能列表
- OSG 模型添加(含自己画的模型,已有模型),对添加的模型做平移 缩放等。
- error C2039: 'addCameraManipulator' : is not a member of 'osgGA
- MFC绘图_OSG窗口调用
- OSG VS2010 win7/win8的配置
- OSG OpenThreads 线程学习(1)
- osg学习第一篇:矩阵
- osg学习第二篇:矩阵(二)
- OSG配置步骤概述 for VS2010
- OSG学习笔记01:OSG的安装