osglight例子

来源:互联网 发布:mac 变色龙 开机引导 编辑:程序博客网 时间:2024/05/16 19:47
先列上两个链接介绍osg中的矩阵变换。
http://www.cnblogs.com/indif/archive/2011/05/13/2045106.html
http://www.cppblog.com/acmiyou/archive/2009/08/24/94292.html
opengl中矩阵是列主序,osg中是行主序。
个人觉得这样从应用上去考虑原因,opengl是最低层低级的软件和硬件的接口,考虑的是高效性
能,osg是高级三维引擎,考虑的是应用和便于理解。opengl中的矩阵使一个16大小的一维数组
,因此在进行矩阵运算的时候只需要指针++就可以到下一个。
而实际的应用中,我们一般理解点是行主序的三个数,
 osg当中:  newpos  =oldpos * T *R    //先执行平移 后执行旋转    (全局坐标系)
因此执行以上的变换,先平移后旋转,很容易理解。
在来说一下MatrixTransform 和PositionAttitudeTransform,一个是矩阵变换一个是位置姿态
,MatrixTransform 是按着矩阵相乘的顺序做变换,而PositionAttitudeTransform是按着SRT的
顺序变换,所以对于PositionAttitudeTransform无论是先设置位置旋转缩放还是后设置结果都
一样。我们从源代码中看个究竟。
对于MatrixTransform 
bool MatrixTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
  
  if (_referenceFrame==RELATIVE_RF)
    {
        matrix.preMult(_matrix);
    }
    
else // absolute
    {
        matrix = _matrix;
    }
    return true;
}
直接做了矩阵的左乘,即_matrix*matrix
而PositionAttitudeTransform
bool PositionAttitudeTransform::computeLocalToWorldMatrix(Matrix& 

matrix,NodeVisitor*) const
{
    if (_referenceFrame==RELATIVE_RF)
    {
        
matrix.preMultTranslate(_position);
        matrix.preMultRotate(_attitude);
        
matrix.preMultScale(_scale);
        matrix.preMultTranslate(-_pivotPoint);
    }
    
else // absolute
    {
        matrix.makeRotate(_attitude);
        
matrix.postMultTranslate(_position);
        matrix.preMultScale(_scale);
        
matrix.preMultTranslate(-_pivotPoint);
    }
    return true;
}
则与顺序无关,完全是按着_scale*_attitude*_position*matrix
而_pivotPoint指定了变换轴,最终把节点移动到变换轴处。
关于RELATIVE_RF和ABSOLUTE_RF我们前面的例子介绍过。
我们回到例子中:
createRoom函数中创建了一个正方体,里面有个
osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform();
pat添加了ModelTransformCallback根据仿真时间重新计算姿态。       pat->setPivotPoint
(loaded_bs.center());
有了上面的介绍我们就很容易理解了,设置节点的包围球中心为轴心。
osg::StateSet* wall = new osg::StateSet;
    wall->setMode
(GL_CULL_FACE,osg::StateAttribute::ON);
设置GL_CULL_FACE打开,即节点的正面被裁切,实现朝着观察者的面不绘制的效果。
createWall绘制一面墙
osgUtil::SmoothingVisitor::smooth(*geom);自动计算了法向量。
createLights创建灯。
我们着重研究一下这个函数
LightSource继承Group,是场景中的光源节点,保存了一个ref_ptr<Light>                  
_light;Light是具体的光照类,内部保存了如下属性:
int _lightnum;                           // OpenGL light number
        Vec4 

_ambient;                           // r, g, b, w
        Vec4 _diffuse;              

             // r, g, b, w
        Vec4 _specular;                          // r, g, 

b, w
        Vec4 _position;                          // x, y, z, w
        Vec3 

_direction;                         // x, y, z
        float _constant_attenuation;   

          // constant
        float _linear_attenuation;               // linear
      
  float _quadratic_attenuation;            // quadratic
        float _spot_exponent; 

                   // exponent
        float _spot_cutoff;                      // 

spread
一个光源的基本属性颜色衰减等,_lightnum是与opengl的光源id相对于,默认为0。
在createLights这个函数中创建了两个光源,把一个点和一个光源添加到MatrixTransform中,
这样模拟了点就是光源的效果,MatrixTransform中添加了AnimationPathCallback一个动画,
光源AnimationPathCallback我们之前的例子中研究过,很按着指定的路径运动。
最后一点    viewer.getCamera()->setCullingMode( viewer.getCamera()->getCullingMode() 
& ~osg::CullStack::SMALL_FEATURE_CULLING);
去除了细节裁剪,这样在场景剔除的时候就不会用到SMALL_FEATURE_CULLING。