查看: 5360|回复: 18

使用osg::Geometry类如何绘制圆柱体

[复制链接]

该用户从未签到

发表于 2008-9-18 17:44:03 | 显示全部楼层 |阅读模式
如题,因为shape类画出来的没办法进行一些复杂操作。我想出来的代码是这样的:
  1. osg::ref_ptr<osg::Node> CreateCylinder()
  2. {
  3.         // Create an object to store geometry in.
  4.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
  5.         // Create an array of four vertices.
  6.         osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
  7.         geom->setVertexArray( v.get() );

  8.         //------------------关键代码,设置圆柱体顶点------------------
  9.         float radius=2.0;//半径
  10.         float fHeight=4.0;//高
  11.         //上底
  12.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  13.         {
  14.                 v->push_back(osg::Vec3(a,0.0f,sqrt(fabs(pow(radius,2)-pow(a,2)))));
  15.         }
  16.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  17.         {
  18.                 v->push_back(osg::Vec3(a,0.0f,-1*sqrt(fabs(pow(radius,2)-pow(a,2)))));
  19.         }
  20.         //下底
  21.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  22.         {
  23.                 v->push_back(osg::Vec3(a,0.0f,sqrt(fabs(pow(radius,2)-pow(a,2))))+osg::Vec3(0.0,fHeight,0.0));
  24.         }
  25.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  26.         {
  27.                 v->push_back(osg::Vec3(a,0.0f,-1*sqrt(fabs(pow(radius,2)-pow(a,2))))+osg::Vec3(0.0,fHeight,0.0));
  28.         }
  29.         float fPoint=204;//总共使用的顶点数
  30.         //----------------------------------------------------------


  31.         // Create an array of four colors.
  32.         osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
  33.         c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  34.         geom->setColorArray( c.get() );
  35.         geom->setColorBinding( osg::Geometry::BIND_OVERALL );
  36.         // Draw a four-vertex quad from the stored data.
  37.         geom->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::POLYGON, 0,fPoint) );
  38.         // Add the Geometry (Drawable) to a Geode and
  39.         // return the Geode.
  40.         osg::ref_ptr<osg::Geode> geode = new osg::Geode;
  41.         geode->addDrawable( geom.get() );

  42.         return geode.get();
  43. }
复制代码
很可惜,运行之后圆柱体始终出不来,不知各位有何良策?

[ 本帖最后由 Sailent 于 2008-9-18 17:45 编辑 ]

该用户从未签到

发表于 2008-9-18 18:16:15 | 显示全部楼层
用osg:: PrimitiveSet:: POLYGON有点问题,应该用TRIANGLES或者QUADS,并且设置了正确的顶点索引才对。此外我没有细看,估计还要改一些东西

我以前做过一个Lathe库,用来生成各种旋转体的,算法什么的都不是很复杂,不过现在找不到了~~

该用户从未签到

发表于 2008-9-18 19:16:09 | 显示全部楼层
OSG官方网站上下载过一个LMBs_OSG_Examples.zip,里面有一个12_CustomDrawable.cpp,可以算是OSG与OPENGL的混合编程吧,如果OPENGL功底还可以的话可以考虑采用这种办法实现。

该用户从未签到

发表于 2008-9-18 22:51:48 | 显示全部楼层
估计图元方式,,,,索引有问题吧~~~你可以看看shape.cpp以及shapedrawable.cpp中的源代码,,里面有相关几何体的绘制~~~~~~~~~~~~

该用户从未签到

 楼主| 发表于 2008-9-19 09:26:09 | 显示全部楼层
原帖由 FlySky 于 2008-9-18 22:51 发表
估计图元方式,,,,索引有问题吧~~~你可以看看shape.cpp以及shapedrawable.cpp中的源代码,,里面有相关几何体的绘制~~~~~~~~~~~~

我看过,shape里面是用glBegin、glEnd实现的,参考价值不大吧……

该用户从未签到

发表于 2008-9-19 12:34:44 | 显示全部楼层
原帖由 Sailent 于 2008-9-19 09:26 发表

我看过,shape里面是用glBegin、glEnd实现的,参考价值不大吧……



OSG本来就是可以和OpenGL结合来绘制~~~~~那样绘制,,,你同样可以设置纹理等各种渲染~~~~~

该用户从未签到

 楼主| 发表于 2008-9-19 15:48:24 | 显示全部楼层
终于画出来了,不过我明明设置材质的漫反射和镜面发射为什么不起作用呢?要怎么设置光照呢?
  1. osg::ref_ptr<osg::Node> CreateCylinder()
  2. {
  3.         // Create an object to store geometry in.
  4.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
  5.         // Create an array of four vertices.
  6.         osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
  7.         geom->setVertexArray( v.get() );

  8.         //------------------关键代码,设置圆柱体顶点------------------
  9.         float radius=2.0;//半径
  10.         float radius2=1.0;
  11.         float fHeight=4.0;//高
  12.         //上底
  13.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  14.         {
  15.                 v->push_back(osg::Vec3(a,0.0f,sqrt(fabs(pow(radius,2)-pow(a,2)))));
  16.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  17.         }
  18.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  19.         {
  20.                 v->push_back(osg::Vec3(a,0.0f,-1*sqrt(fabs(pow(radius,2)-pow(a,2)))));
  21.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,-1*sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  22.         }

  23.         float fPoint=204;//总共使用的顶点数
  24.         //----------------------------------------------------------


  25.         // Create an array of four colors.
  26.         osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
  27.         c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  28.         geom->setColorArray( c.get() );
  29.         geom->setColorBinding( osg::Geometry::BIND_OVERALL );
  30.         // Draw a four-vertex quad from the stored data.
  31.         geom->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::TRIANGLE_STRIP, 0,fPoint) );
  32.         // Add the Geometry (Drawable) to a Geode and
  33.         // return the Geode.
  34.         osg::ref_ptr<osg::Geode> geode = new osg::Geode;
  35.         geode->addDrawable( geom.get() );

  36.         osg::Matrix RoLast1;
  37.         RoLast1.makeRotate(180.0*3.14159265/180.0,osg::Vec3f(1.0,0.0,0.0));

  38.         osg::Matrix RoLast2;
  39.         RoLast2.makeTranslate(osg::Vec3(0.0,2.75,0.0));

  40.         osg::ref_ptr<osg::MatrixTransform> TransNode = new osg::MatrixTransform;
  41.         TransNode->addChild(geode.get());
  42.         TransNode->setMatrix(RoLast1*RoLast2);

  43.         osg::StateSet* state4 = TransNode->getOrCreateStateSet();
  44.         osg::ref_ptr<osg::Material> mat3 = new osg::Material;
  45.         //漫反射光(决定物体颜色)
  46.         mat3->setDiffuse( osg::Material::FRONT_AND_BACK,
  47.                 osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
  48.         //镜面反射光
  49.         mat3->setSpecular( osg::Material::FRONT_AND_BACK,
  50.                 osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  51.         //环境反射光
  52.         mat3->setShininess( osg::Material::FRONT_AND_BACK, 128.f );
  53.         state4->setAttribute( mat3.get() );
  54.         state4->setRenderingHint( osg::StateSet::OPAQUE_BIN );

  55.         return TransNode.get();
  56. }
复制代码

[ 本帖最后由 Sailent 于 2008-9-19 15:51 编辑 ]

该用户从未签到

发表于 2008-9-19 17:19:13 | 显示全部楼层
没有设置法线吧?setNormalArray

该用户从未签到

 楼主| 发表于 2008-9-19 17:38:30 | 显示全部楼层
可是应该往哪个方向设呢?要设多少条呢?要设成圆形的一圈吗?

该用户从未签到

 楼主| 发表于 2008-9-19 17:50:48 | 显示全部楼层
已经加了法线了,怎么它还是白色的呢?
  1. osg::ref_ptr<osg::Node> CreateCylinder()
  2. {
  3.         // Create an object to store geometry in.
  4.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
  5.         // Create an array of four vertices.
  6.         osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
  7.         geom->setVertexArray( v.get() );

  8.         //------------------关键代码,设置圆柱体顶点------------------
  9.         float radius=2.0;//半径
  10.         float radius2=1.0;
  11.         float fHeight=4.0;//高
  12.         //上底
  13.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  14.         {
  15.                 v->push_back(osg::Vec3(a,0.0f,sqrt(fabs(pow(radius,2)-pow(a,2)))));
  16.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  17.         }
  18.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  19.         {
  20.                 v->push_back(osg::Vec3(a,0.0f,-1*sqrt(fabs(pow(radius,2)-pow(a,2)))));
  21.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,-1*sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  22.         }

  23.         float fPoint=204;//总共使用的顶点数       
  24.        
  25.         //设置法线
  26.         osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
  27.         geom->setNormalArray( n.get() );
  28.         geom->setNormalBinding( osg::Geometry::BIND_OVERALL );
  29.         n->push_back( osg::Vec3( 0.0f,1.0f, 0.0f ) );
  30.         //----------------------------------------------------------

  31.         // Create an array of four colors.
  32.         osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
  33.         c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  34.         geom->setColorArray( c.get() );
  35.         geom->setColorBinding( osg::Geometry::BIND_OVERALL );
  36.         // Draw a four-vertex quad from the stored data.
  37.         geom->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::TRIANGLE_STRIP, 0,fPoint) );
  38.         // Add the Geometry (Drawable) to a Geode and
  39.         // return the Geode.
  40.         osg::ref_ptr<osg::Geode> geode = new osg::Geode;
  41.         geode->addDrawable( geom.get() );

  42.         osg::Matrix RoLast1;
  43.         RoLast1.makeRotate(180.0*3.14159265/180.0,osg::Vec3f(1.0,0.0,0.0));

  44.         osg::Matrix RoLast2;
  45.         RoLast2.makeTranslate(osg::Vec3(0.0,2.75,0.0));

  46.         osg::ref_ptr<osg::MatrixTransform> TransNode = new osg::MatrixTransform;
  47.         TransNode->addChild(geode.get());
  48.         TransNode->setMatrix(RoLast1*RoLast2);

  49.         osg::StateSet* state4 = TransNode->getOrCreateStateSet();
  50.         osg::ref_ptr<osg::Material> mat3 = new osg::Material;
  51.         //漫反射光(决定物体颜色)
  52.         mat3->setDiffuse( osg::Material::FRONT_AND_BACK,
  53.                 osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
  54.         //镜面反射光
  55.         mat3->setSpecular( osg::Material::FRONT_AND_BACK,
  56.                 osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  57.         //环境反射光
  58.         mat3->setShininess( osg::Material::FRONT_AND_BACK, 128.f );
  59.         state4->setAttribute( mat3.get() );
  60.         state4->setRenderingHint( osg::StateSet::OPAQUE_BIN );

  61.         return TransNode.get();
  62. }
复制代码

该用户从未签到

发表于 2008-9-19 18:25:12 | 显示全部楼层
要得到正确效果的话,法线的数量应该等同于顶点的数量,即每个顶点都要设置法线。

觉得麻烦的话也可以选用SmoothVisitor,不过它会自动生成一种模拟表面光滑效果的法线坐标,比较有意思。

该用户从未签到

 楼主| 发表于 2008-9-22 09:53:02 | 显示全部楼层
  1. osg::ref_ptr<osg::Node> CreateCylinder()
  2. {
  3.         // Create an object to store geometry in.
  4.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
  5.         // Create an array of four vertices.
  6.         osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
  7.         geom->setVertexArray( v.get() );

  8.         //------------------关键代码,设置圆柱体顶点------------------
  9.         float radius=2.0;//半径
  10.         float radius2=1.0;
  11.         float fHeight=4.0;//高
  12.         //上底
  13.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  14.         {
  15.                 v->push_back(osg::Vec3(a,0.0f,sqrt(fabs(pow(radius,2)-pow(a,2)))));
  16.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  17.         }
  18.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  19.         {
  20.                 v->push_back(osg::Vec3(a,0.0f,-1*sqrt(fabs(pow(radius,2)-pow(a,2)))));
  21.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,-1*sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  22.         }

  23.         float fPoint=204;//总共使用的顶点数       
  24.        
  25.         //设置法线
  26.         osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
  27.         geom->setNormalArray( n.get() );
  28.         geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
  29. //        n->push_back( osg::Vec3( 0.0f,1.0f, 0.0f ) );
  30.         float x2=radius*fHeight*fHeight/(fHeight*fHeight+pow((radius-radius2),2));
  31.         float x3=x2*(radius-radius2)/fHeight;
  32.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  33.         {
  34.                 n->push_back(osg::Vec3(a*(x2/radius),0.0f,sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0));
  35.         }
  36.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  37.         {
  38.                 n->push_back(osg::Vec3(a*(x2/radius),0.0f,-1*sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0));
  39.         }

  40.        
  41.         //----------------------------------------------------------

  42.         // Create an array of four colors.
  43.         osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
  44.         c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  45.         geom->setColorArray( c.get() );
  46.         geom->setColorBinding( osg::Geometry::BIND_OVERALL );
  47.         // Draw a four-vertex quad from the stored data.
  48.         geom->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::TRIANGLE_STRIP, 0,fPoint) );

  49.         //使用smoothingVisitor
  50.         osgUtil::SmoothingVisitor::smooth(*geom.get());

  51.         // Add the Geometry (Drawable) to a Geode and
  52.         // return the Geode.
  53.         osg::ref_ptr<osg::Geode> geode = new osg::Geode;
  54.         geode->addDrawable(geom.get());

  55.         osg::Matrix RoLast1;
  56.         RoLast1.makeRotate(180.0*3.14159265/180.0,osg::Vec3f(1.0,0.0,0.0));

  57.         osg::Matrix RoLast2;
  58.         RoLast2.makeTranslate(osg::Vec3(0.0,2.75,0.0));

  59.         osg::ref_ptr<osg::MatrixTransform> TransNode = new osg::MatrixTransform;
  60.         TransNode->addChild(geode.get());
  61.         TransNode->setMatrix(RoLast1*RoLast2);

  62.         osg::StateSet* state4 = TransNode->getOrCreateStateSet();
  63.         osg::ref_ptr<osg::Material> mat3 = new osg::Material;
  64.         //漫反射光(决定物体颜色)
  65.         mat3->setDiffuse( osg::Material::FRONT_AND_BACK,
  66.                 osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
  67.         //镜面反射光
  68.         mat3->setSpecular( osg::Material::FRONT_AND_BACK,
  69.                 osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  70.         //环境反射光
  71.         mat3->setShininess( osg::Material::FRONT_AND_BACK, 128.f );
  72.         state4->setAttribute( mat3.get() );
  73.         state4->setRenderingHint( osg::StateSet::OPAQUE_BIN );

  74.         return TransNode.get();
  75. }
复制代码
是这样吗?还是没有效果啊~~

该用户从未签到

发表于 2008-9-22 10:14:30 | 显示全部楼层
您的法线作了归一化处理了吗?还有您的数学运算我不知道如何实现的,我印象中应该没有这么多sqrt和pow才对~~

下个月我打算启动一个新的osgModeling工程的计划,把所有3dsmax等软件中常用的基本体都用Geometry的派生类来实现,并计划编写Extrude(挤压),Lathe(旋转体),Loft(放样),BeizierSurface和NurbsSurface这几种常用建模手段类,远期还希望包括Subdivision(细化),BoolOperator(布尔)等高级建模功能。希望到时候能为大家提供一些方便。

该用户从未签到

 楼主| 发表于 2008-9-22 10:38:18 | 显示全部楼层
原帖由 array 于 2008-9-22 10:14 发表
您的法线作了归一化处理了吗?还有您的数学运算我不知道如何实现的,我印象中应该没有这么多sqrt和pow才对~~

下个月我打算启动一个新的osgModeling工程的计划,把所有3dsmax等软件中常用的基本体都用Geometry的派 ...

归一化处理?代码就这么多啊,最多加了下面一点:
  1. osgViewer::Viewer viewer;
  2. viewer.SetSceneData(CreateCyliner().get());
  3. viewer.run();
复制代码
而且好像用了smoothingVisitor之后,自己写的法线设置就应该不起作用了,但运行的时候外面是黑的,里面是亮的,怎么反过来呢?

该用户从未签到

 楼主| 发表于 2008-9-22 10:53:09 | 显示全部楼层
我的数学运算其实就是实现:x*x+y*y=r*r这样圆的函数啊,设置每个顶点为下图所示。X就是循环控制的精度了。

[ 本帖最后由 Sailent 于 2008-9-22 10:55 编辑 ]
math1.JPG

该用户从未签到

 楼主| 发表于 2008-9-22 11:07:07 | 显示全部楼层
将法线算法做了一些改进,取消了smoothingvisitor,但为什么会有2根黑黑的线呢?
  1. osg::ref_ptr<osg::Node> CreateCylinder()
  2. {
  3.         // Create an object to store geometry in.
  4.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
  5.         // Create an array of four vertices.
  6.         osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
  7.         geom->setVertexArray( v.get() );

  8.         //------------------关键代码,设置圆柱体顶点------------------
  9.         float radius=2.0;//半径
  10.         float radius2=1.0;
  11.         float fHeight=4.0;//高
  12.         //上底
  13.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  14.         {
  15.                 v->push_back(osg::Vec3(a,0.0f,sqrt(fabs(pow(radius,2)-pow(a,2)))));
  16.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  17.         }
  18.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  19.         {
  20.                 v->push_back(osg::Vec3(a,0.0f,-1*sqrt(fabs(pow(radius,2)-pow(a,2)))));
  21.                 v->push_back(osg::Vec3(a*(radius2/radius),0.0f,-1*sqrt(fabs(pow(radius2,2)-pow(a*(radius2/radius),2))))+osg::Vec3(0.0,fHeight,0.0));
  22.         }

  23.         float fPoint=204;//总共使用的顶点数       
  24.        
  25.         //设置法线
  26.         osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
  27.         geom->setNormalArray( n.get() );
  28.         geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX);
  29. //        n->push_back( osg::Vec3( 0.0f,0.0f, 1.0f ) );
  30.         float x2=radius*fHeight*fHeight/(fHeight*fHeight+pow((radius-radius2),2));
  31.         float x3=x2*(radius-radius2)/fHeight;
  32.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  33.         {
  34.                 n->push_back(osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(a*(x2/radius),0.0f,sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0)));
  35.                 n->push_back(osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(a*(x2/radius),0.0f,sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0)));
  36.         }
  37.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  38.         {
  39.                 n->push_back(osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(a*(x2/radius),0.0f,-1*sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0)));
  40.                 n->push_back(osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(a*(x2/radius),0.0f,-1*sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0)));
  41.         }

  42.        
  43.         //----------------------------------------------------------

  44.         // Create an array of four colors.
  45.         osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
  46.         c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  47.         geom->setColorArray( c.get() );
  48.         geom->setColorBinding( osg::Geometry::BIND_OVERALL );
  49.         // Draw a four-vertex quad from the stored data.
  50.         geom->addPrimitiveSet(new osg::DrawArrays( osg::PrimitiveSet::TRIANGLE_STRIP, 0,fPoint) );

  51.         //使用smoothingVisitor
  52. //        osgUtil::SmoothingVisitor::smooth(*geom.get());

  53.         // Add the Geometry (Drawable) to a Geode and
  54.         // return the Geode.
  55.         osg::ref_ptr<osg::Geode> geode = new osg::Geode;
  56.         geode->addDrawable(geom.get());

  57.         osg::Matrix RoLast1;
  58.         RoLast1.makeRotate(180.0*3.14159265/180.0,osg::Vec3f(1.0,0.0,0.0));

  59.         osg::Matrix RoLast2;
  60.         RoLast2.makeTranslate(osg::Vec3(0.0,2.75,0.0));

  61.         osg::ref_ptr<osg::MatrixTransform> TransNode = new osg::MatrixTransform;
  62.         TransNode->addChild(geode.get());
  63.         TransNode->setMatrix(RoLast1*RoLast2);

  64.         osg::StateSet* state4 = TransNode->getOrCreateStateSet();
  65.         osg::ref_ptr<osg::Material> mat3 = new osg::Material;
  66.         //漫反射光(决定物体颜色)
  67.         mat3->setDiffuse( osg::Material::FRONT_AND_BACK,
  68.                 osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
  69.         //镜面反射光
  70.         mat3->setSpecular( osg::Material::FRONT_AND_BACK,
  71.                 osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
  72.         //环境反射光
  73.         mat3->setShininess( osg::Material::FRONT_AND_BACK, 128.f );
  74.         state4->setAttribute( mat3.get() );
  75.         state4->setRenderingHint( osg::StateSet::OPAQUE_BIN );

  76.         return TransNode.get();
  77. }
复制代码

该用户从未签到

发表于 2008-9-22 11:31:24 | 显示全部楼层
法线是必须进行归一化的,也就是法线向量的模必须为1。否则OpenGL的光照计算会不正确。建议不要直接用setMode(GL_NORMALIZE),会大大增加场景开销

使用SmoothVisitor的话,就不要再自己计算法线了,还有您的多边形方向可能反了,所以SmoothVisitor的法线方向也是反的。

用圆的方程x*x+y*y=r*r的话,精度损失恐怕不小,计算式看起来也有点恐怖,尤其sqrt和pow都是编程的时候应该尽量避免的;通常的方法是使用三角函数。

您所说的那两条线可能是圆锥体没有闭合的缘故,细看就知道了,事实上您的圆锥体是有缺口的。这恐怕也是浮点数以及精度的损失计算造成的,不要奢望C语言的浮点数计算准确,也永远都不要把两个浮点数作“==”的比较

该用户从未签到

 楼主| 发表于 2008-9-22 11:57:40 | 显示全部楼层
归一化的结果是精确为1还是近似为1(0.9999999或者1.00000001)呢?通过数学计算让模为1的话肯定都是近似于1的。
三角函数画圆的方法应该是(r*cos(a),0,r*sin(a))吧(0<=a<=3.14)。
还有,我说的两条线是由光照引起的,像截图里的那样。
temp4.JPG

该用户从未签到

 楼主| 发表于 2008-9-22 12:35:15 | 显示全部楼层
归一化处理后那两条黑线没有了,设置法线代码改成这样就可以了:
  1.         //设置法线
  2.         osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
  3.         geom->setNormalArray( n.get() );
  4.         geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX);
  5. //        n->push_back( osg::Vec3( 0.0f,0.0f, 1.0f ) );
  6.         float x2=radius*fHeight*fHeight/(fHeight*fHeight+pow((radius-radius2),2));
  7.         float x3=x2*(radius-radius2)/fHeight;
  8.         osg::Vec3 Vec3temp;
  9.         for (float a=-1.0*radius;a<=1.0*radius+0.0001;a+=radius/25.0)
  10.         {
  11.                 Vec3temp=osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(a*(x2/radius),0.0f,sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0));
  12.                 Vec3temp=Vec3temp*(1.0/sqrt(pow(Vec3temp.x(),2)+pow(Vec3temp.y(),2)+pow(Vec3temp.z(),2)));//归一化处理,让法线模为1.
  13.                 n->push_back(Vec3temp);
  14.                 n->push_back(Vec3temp);
  15.         }
  16.         for (float a=1.0*radius;a>=-1.0*radius-0.0001;a-=radius/25.0)
  17.         {
  18.                 Vec3temp=osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(a*(x2/radius),0.0f,-1*sqrt(fabs(pow(x2,2)-pow(a*(x2/radius),2))))+osg::Vec3(0.0,x3,0.0));
  19.                 Vec3temp=Vec3temp*(1.0/sqrt(pow(Vec3temp.x(),2)+pow(Vec3temp.y(),2)+pow(Vec3temp.z(),2)));
  20.                 n->push_back(Vec3temp);
  21.                 n->push_back(Vec3temp);
  22.         }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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