先来看看ShapeDrawable,这个类继承Drawable,是用来绘制简单的几何体。
在Drawable中定义了ref_ptr<Shape> _shape;几何体的类型基类,
class Sphere;
class Box;
class Cone;
class Cylinder;
class Capsule;
class InfinitePlane;
class TriangleMesh;
class ConvexHull;
class HeightField;
class CompositeShape;
都是继承Shape,这些是osg中自带的几何体。
我们从Drawable的drawImplementation开始研究它是怎么实现的,之前我们说过Drawable的绘制是从古drawImplementation这个函数,ShapeDrawable同样是这个函数,进去看看:
void ShapeDrawable::drawImplementation(RenderInfo& renderInfo) const
{
osg::State& state = *renderInfo.getState();
GLBeginEndAdapter& gl = state.getGLBeginEndAdapter();
if (_shape.valid())
{
gl.Color4fv(_color.ptr());
DrawShapeVisitor dsv(state,_tessellationHints.get());
_shape->accept(dsv);
}
}
有这么一段函数,GLBeginEndAdapter先把它放一边,一会再研究。看看DrawShapeVisitor,通过这个Visitor绘制,DrawShapeVisitor继承ConstShapeVisitor,里面实现了以上类型的几何体的绘制,因此,在绘制之前必须给Drawable指定shape。
接下来看看GLBeginEndAdapter,它是osg中的一中OpenGL,Begin、End形式的绘制类,里面可以找到OpenGL基本函数对应的函数。进入void GLBeginEndAdapter::End(),可以看到使用顶点数组绘制的。关于基本几何体具体的绘制,这里就不多说了,可以看相应的函数。void DrawShapeVisitor::apply(const Sphere& sphere)这是球的绘制,模式类似OpenGL的绘制过程。
回到例子中,在createScene()中绘制了两个球,一个圆和一个坐标轴,代表地球、太阳和地球的轨迹。
关键在const double r_earth = 6378.137;
const double r_sun = 695990.0;
const double AU = 149697900.0;这里,数值比较大。由于绘制的场景比较大,远近平面的精度不够。
看看在《Cookbook》这本书中描述吧。
As many early devices have
only a 16-bit depth buffer or 24-bit one, you may not be able to maintain a huge distance (in the solar system) between the near and the far plane. If you force setting the near plane to a small value and the far plane to a very large one, the rendering of nearby objects will cause the classic Z-fighting problem because there is not enough precision to resolve the distance.
The best solution is to buy a new graphics card supporting a 32-bit buffer. But to keep the
program portable, we had better find some other solutions, for instance, the depth partition
algorithm in this recipe. To introduce this algorithm in one sentence—it partitions the scene into several parts and renders them separately. Every part has its own near and far values and the distance between them is short enough to avoid the precision problem.
这就是本例中所要说明的问题,
通过深度分离的算法,使远近的物体分别的渲染,每个部分都有自己的远近平面,这样就避免了精度的问题。
看看view中的setUpDepthPartition方法实现:
首先,获取了场景中所有的相机,每个相机执行了setUpDepthPartitionForCamera(itr->get(), dsp);函数,在setUpDepthPartitionForCamera中移除了相机本身,然后添加了两个相机,一个指向远平面,一个指向近平面。
远相机:
slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 1);
近相机:
slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 0);MyUpdateSlaveCallback中的updateSlave获取getDepthRange根据指定的属性进行计算,通过这种方式实现,远景近景分别渲染。
在Drawable中定义了ref_ptr<Shape> _shape;几何体的类型基类,
class Sphere;
class Box;
class Cone;
class Cylinder;
class Capsule;
class InfinitePlane;
class TriangleMesh;
class ConvexHull;
class HeightField;
class CompositeShape;
都是继承Shape,这些是osg中自带的几何体。
我们从Drawable的drawImplementation开始研究它是怎么实现的,之前我们说过Drawable的绘制是从古drawImplementation这个函数,ShapeDrawable同样是这个函数,进去看看:
void ShapeDrawable::drawImplementation(RenderInfo& renderInfo) const
{
osg::State& state = *renderInfo.getState();
GLBeginEndAdapter& gl = state.getGLBeginEndAdapter();
if (_shape.valid())
{
gl.Color4fv(_color.ptr());
DrawShapeVisitor dsv(state,_tessellationHints.get());
_shape->accept(dsv);
}
}
有这么一段函数,GLBeginEndAdapter先把它放一边,一会再研究。看看DrawShapeVisitor,通过这个Visitor绘制,DrawShapeVisitor继承ConstShapeVisitor,里面实现了以上类型的几何体的绘制,因此,在绘制之前必须给Drawable指定shape。
接下来看看GLBeginEndAdapter,它是osg中的一中OpenGL,Begin、End形式的绘制类,里面可以找到OpenGL基本函数对应的函数。进入void GLBeginEndAdapter::End(),可以看到使用顶点数组绘制的。关于基本几何体具体的绘制,这里就不多说了,可以看相应的函数。void DrawShapeVisitor::apply(const Sphere& sphere)这是球的绘制,模式类似OpenGL的绘制过程。
回到例子中,在createScene()中绘制了两个球,一个圆和一个坐标轴,代表地球、太阳和地球的轨迹。
关键在const double r_earth = 6378.137;
const double r_sun = 695990.0;
const double AU = 149697900.0;这里,数值比较大。由于绘制的场景比较大,远近平面的精度不够。
看看在《Cookbook》这本书中描述吧。
As many early devices have
only a 16-bit depth buffer or 24-bit one, you may not be able to maintain a huge distance (in the solar system) between the near and the far plane. If you force setting the near plane to a small value and the far plane to a very large one, the rendering of nearby objects will cause the classic Z-fighting problem because there is not enough precision to resolve the distance.
The best solution is to buy a new graphics card supporting a 32-bit buffer. But to keep the
program portable, we had better find some other solutions, for instance, the depth partition
algorithm in this recipe. To introduce this algorithm in one sentence—it partitions the scene into several parts and renders them separately. Every part has its own near and far values and the distance between them is short enough to avoid the precision problem.
这就是本例中所要说明的问题,
通过深度分离的算法,使远近的物体分别的渲染,每个部分都有自己的远近平面,这样就避免了精度的问题。
看看view中的setUpDepthPartition方法实现:
首先,获取了场景中所有的相机,每个相机执行了setUpDepthPartitionForCamera(itr->get(), dsp);函数,在setUpDepthPartitionForCamera中移除了相机本身,然后添加了两个相机,一个指向远平面,一个指向近平面。
远相机:
slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 1);
近相机:
slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 0);MyUpdateSlaveCallback中的updateSlave获取getDepthRange根据指定的属性进行计算,通过这种方式实现,远景近景分别渲染。