张曦 发表于 2017-3-28 19:30:39

OSG添加图片结果纹理扭曲

在安卓端做加载天空盒的项目,用的代码是书中的例子,但是加载的纹理一直是扭曲的,求解答!谢谢大家!代码用的是PC端的,自己进行了相应的修改可以移植到安卓端,代码如下:
osg::ref_ptr<osg::TextureCubeMap> readCubeMap()
{
        osg::ref_ptr<osg::TextureCubeMap> cubemap = new osg::TextureCubeMap;

        osg::ref_ptr<osg::Image> imagePosX = osgDB::readImageFile("right.jpg");
        osg::ref_ptr<osg::Image> imageNegX = osgDB::readImageFile("left.jpg");
        osg::ref_ptr<osg::Image> imagePosY = osgDB::readImageFile("front.jpg");
        osg::ref_ptr<osg::Image> imageNegY = osgDB::readImageFile("back.jpg");
        osg::ref_ptr<osg::Image> imagePosZ = osgDB::readImageFile("up.jpg");
        osg::ref_ptr<osg::Image> imageNegZ = osgDB::readImageFile("down.jpg");

        if (imagePosX.get() && imageNegX.get() && imagePosY.get() && imageNegY.get() && imagePosZ.get() && imageNegZ.get())
        {
                //设置立方图的六个面的贴图
                cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX.get());
                cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX.get());
                cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY.get());
                cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY.get());
                cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ.get());
                cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ.get());

                //设置纹理环绕模式
                cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
                cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
                cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);

                //设置滤波:线形和mipmap
                cubemap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
                cubemap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
        }

        return cubemap.get();
}

//更新立方体图纹理
struct TexMatCallback : public osg::NodeCallback
{
public:

        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::Quat q = MV.getRotate();
                          const osg::Matrix C = osg::Matrix::rotate( q.inverse() );

                          //设置纹理矩阵
                          _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;
        }
};

//创建天空盒
osg::ref_ptr<osg::Node> createSkyBox()
{
       

        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();


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

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

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

        //设置立方图纹理
        osg::ref_ptr<osg::TextureCubeMap> skymap = readCubeMap();
        stateset->setTextureAttributeAndModes(0, skymap.get(), osg::StateAttribute::ON| osg::StateAttribute::OVERRIDE);

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

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

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

        osg::ref_ptr<osg::Drawable> drawable = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),1));

        //把球体加入到叶节点
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->setCullingActive(false);
        geode->setStateSet( stateset.get());
        geode->addDrawable(drawable.get());

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

        //osg::ref_ptr<osg::ClearNode> clearNode = new osg::ClearNode;
        //clearNode->setCullCallback(new TexMatCallback(*tm));
        //clearNode->addChild(transform.get());

        return geode.get();
}

int main()
{
        osg::ref_ptr<osgViewer::Viewer> viewer= new osgViewer::Viewer();

        osg::ref_ptr<osg::Group> rootnode = new osg::Group();

        //加入天空盒
        rootnode->addChild(createSkyBox());

        //优化场景数据
        osgUtil::Optimizer optimzer;
        optimzer.optimize(rootnode.get());

        viewer->setSceneData(rootnode.get());

        viewer->realize();

        viewer->run();

        return 0 ;
}
页: [1]
查看完整版本: OSG添加图片结果纹理扭曲