查看: 2441|回复: 6

纹理映射问题

[复制链接]

该用户从未签到

发表于 2009-3-23 15:10:18 | 显示全部楼层 |阅读模式
这是我运行的场景图,我做的是个天空盒子,但是不知道说什么会有一条一条的条带呢?下面是相关代码:
osg::Node* createSkyBox(osg::BoundingSphere bs)
{
    osg::StateSet* stateset = new osg::StateSet();

    //设置纹理映射方式,指定为替代方式,即纹理中的颜色代替原来的颜色
    osg::TexEnv* te = new osg::TexEnv;
    te->setMode(osg::TexEnv::REPLACE);
    stateset->setTextureAttributeAndModes(0, te, osg::StateAttribute::ON);

    //自动生成纹理坐标,反射方式(REFLECTION_MAP)
    /*
    NORMAL_MAP 标准模式-立方图纹理
    REFLECTION_MAP 反射模式-球体纹理
    SPHERE_MAP 球体模型-球体纹理
    */
    osg::TexGen *tg = new osg::TexGen;
    tg->setMode(osg::TexGen::NORMAL_MAP);
    stateset->setTextureAttributeAndModes(0, tg, osg::StateAttribute::ON);

//    //设置纹理矩阵
    osg::TexMat *tm = new osg::TexMat;
    stateset->setTextureAttribute(0, tm);

    //设置立方图纹理
    osg::TextureCubeMap* skymap = readCubeMap();
    stateset->setTextureAttributeAndModes(0, skymap, osg::StateAttribute::ON);

    stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
    stateset->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );

    //将深度设置为远平面
    osg:epth* depth = new osg::Depth;
    depth->setFunction(osg::Depth::ALWAYS);
    depth->setRange(1.0,1.0);//远平面   
    stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);

    //设置渲染顺序为-1,先渲染
    stateset->setRenderBinDetails(-1,"RenderBin");

//    osg::Drawable* drawable = new osg::ShapeDrawable(new osg::Box(bb.center(),bb.width()));
    osg::Drawable* drawable = new osg::ShapeDrawable(new osg::Sphere(bs.center(),bs.radius()));
    //把球体加入到叶节点
    osg::Geode* geode = new osg::Geode;
    geode->setCullingActive(false);
    geode->setStateSet( stateset );
    geode->addDrawable(drawable);

    //设置变换
//    osg::Transform* transform = new MoveEarthySkyWithEyePointTransform();
//    transform->setCullingActive(false);
//    transform->addChild(geode);

    osg::ClearNode* clearNode = new osg::ClearNode;
    clearNode->setRequiresClear(true);
    clearNode->setCullCallback(new TexMatCallback(*tm));
//    clearNode->addChild(transform);
    clearNode->addChild(geode);

    return clearNode;
//    return transform;
}

其中
struct TexMatCallback:public osg::NodeCallback
{
    TexMatCallback(osg::TexMat& tm):_texMat(tm)
    {
    }

    virtual void operator()(osg::Node* node,osg::NodeVisitor* nv)
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if(cv)
        {
             //得到模型视图矩阵并设置旋转角度
              const osg::Matrix& MV = *(cv->getModelViewMatrix());
              const osg::Matrix R = osg::Matrix::rotate( osg::DegreesToRadians(112.0f), 0.0f,0.0f,1.0f)*osg::Matrix::rotate( osg::DegreesToRadians(90.0f), 1.0f,0.0f,0.0f);

              osg:uat q = MV.getRotate();
              const osg::Matrix C = osg::Matrix::rotate( q.inverse() );

              //设置纹理矩阵
    //          _texMat.setMatrix(C);
              _texMat.setMatrix( C*R );
        }

         traverse(node,nv);
    }
          //纹理矩阵
      osg::TexMat& _texMat;
};

//一个变换类,使天空盒绕视点旋转
class MoveEarthySkyWithEyePointTransform : public osg::Transform
{
public:
    //局部矩阵计算成世界矩阵
    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if (cv)
        {
            osg::Vec3 eyePointLocal = cv->getEyeLocal();
            matrix.preMult(osg::Matrix::translate(eyePointLocal));
        }
        return true;
    }

    //世界矩阵计算为局部矩阵
    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if (cv)
        {
            osg::Vec3 eyePointLocal = cv->getEyeLocal();
            matrix.postMult(osg::Matrix::translate(-eyePointLocal));
        }
        return true;
    }
};
jietu.jpg

该用户从未签到

发表于 2009-3-23 15:27:12 | 显示全部楼层

加个问题

osgrawable* drawable = new osg::ShapeDrawable(new osg::Sphere(bs.center(),bs.radius()));
我把这句改为
osg:Drawable* drawable = new osg::ShapeDrawable(new osg::Box(bs.center(),bs.radius()));
后 天空盒就就看不到纹理了 就只有一个立方体盒子
怎么解决?

该用户从未签到

 楼主| 发表于 2009-3-23 15:34:23 | 显示全部楼层
是啊,想弄一个天空盒子,但不会像图中那样冗余,只要天空上方就行,不知道用什么方法来解决?谢谢

该用户从未签到

发表于 2009-3-23 16:55:35 | 显示全部楼层

改成下面的语句试试

//设置变换
    osg::Transform* transform = new MoveEarthySkyWithEyePointTransform();
  transform->setCullingActive(false);
   transform->addChild(geode);

    osg::ClearNode* clearNode = new osg::ClearNode;
    clearNode->setRequiresClear(true);
    clearNode->setCullCallback(new TexMatCallback(*tm));
   clearNode->addChild(transform);
   

    return clearNode;
//    return transform

该用户从未签到

 楼主| 发表于 2009-3-23 19:14:59 | 显示全部楼层
不对啊,这些都已经试过了。还是不知道有什么方法可以解决的,请高人帮忙。谢谢

该用户从未签到

发表于 2009-3-23 22:23:01 | 显示全部楼层
这个天空盒的实现方法似乎很悠久了,而且有些考虑似乎不太全面;我以前也常遇到各种不知其然的错误。
《你所不知的OSG》后面的章节会提供另一种天空盒的实现方法(直接重写traverse而非使用回调)

该用户从未签到

 楼主| 发表于 2009-3-24 08:24:09 | 显示全部楼层
不知道array版主能不能给点提示,因为要急着做出个天空盒子来,谢谢!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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