利用C++和OSG库,已经写好了关于长方体6个面贴图的程序,但是很奇怪的是,长方体坐标中心选择(0,0,0)则贴图正确(6个不同的卡通图案);长方体坐标中心选择(691940.61, 4871848.22, 236.13),该坐标值是我三维模型中某个大楼的坐标,贴图结果错误(6个面的贴图为纯色或者花条,无图案)。
请教问题出在何处
// stdafx.h
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Quat>
#include <osg/Matrix>
#include <osg/ShapeDrawable> //预定义几何体类,派生自osg::Drawable类。OSG中使用该类来将OSG内嵌的预定义几何体与osg::Drawable关联以渲染这些几何体
#include <osg/Transform> //一个组节点,所有子节点都通过4x4矩阵进行变换,通常用于在场景中定位对象,生成轨迹球功能或用于动画
#include <osg/NodeCallback > //节点更新回调
#include <osg/Depth> //封装OpenGL glDepthFunc / Mask / Range函数
#include <osg/CullFace>
#include <osg/TexMat>
#include <osg/TexGen> //指定用于自动生成纹理坐标的函数,可以设置纹理的计算方式是以物体坐标空间还是相机坐标空间来进行不同的计算
#include <osg/TexEnv>
#include <osg/TextureCubeMap> //立方体纹理映射
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
//.cpp
//读取立方图
osg::ref_ptr<osg::TextureCubeMap> readCubeMap()
{
//读取纹理图片
/*读取立方图纹理贴图时,纹理贴图要与立方体的各个面一一对应
POSITIVE_X=0, //Left X正方向
NEGATIVE_X=1, //Right X负方向
POSITIVE_Y=2, //Front Y正方向
NEGATIVE_Y=3, //Back Y负方向
POSITIVE_Z=4, //Up Z正方向
NEGATIVE_Z=5 //Down Z负方向
*/
osg::ref_ptr<osg::Image> imagePosX = osgDB::readImageFile("F:/changchun/POSITIVE_X.bmp");
osg::ref_ptr<osg::Image> imageNegX = osgDB::readImageFile("F:/changchun/NEGATIVE_X.bmp");
osg::ref_ptr<osg::Image> imagePosY = osgDB::readImageFile("F:/changchun/POSITIVE_Y.bmp");
osg::ref_ptr<osg::Image> imageNegY = osgDB::readImageFile("F:/changchun/NEGATIVE_Y.bmp");
osg::ref_ptr<osg::Image> imagePosZ = osgDB::readImageFile("F:/changchun/POSITIVE_Z.bmp");
osg::ref_ptr<osg::Image> imageNegZ = osgDB::readImageFile("F:/changchun/NEGATIVE_Z.bmp");
//创建立方体纹理对象
osg::ref_ptr<osg::TextureCubeMap> cubemap = new osg::TextureCubeMap();
//判断纹理图片存在
if (imagePosX.get() && imageNegX.get() && imagePosY.get() && imageNegY.get() && imagePosZ.get() && imageNegZ.get())
{
//设置立方图的6个面的贴图
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());
//设置纹理环绕模式
/*设置纹理的坐标/包装模式
enum WrapParmeter
{
WRAP_S, //x轴
WRAP_T, //y轴
WRAP_T //z轴
};
enum WrapMode
{
CLAMP, //截取
CLAMP_TO_EDGE, //边框始终被忽略
CLAMP_TO_BORDER, //它使用的纹理取自图像的边框,没有边框就使用常量边框的颜色
REPEAT, //纹理的重复映射
MIRROR //纹理镜像的重复映射
};
*/
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
/*设置纹理的过滤方法/过滤处理
enum FilterParameter
{
MIN_FILTER, //缩小
MAG_FILTER //放大
};
enum FilterMode
{
LINEAR, //以周围4个像素的平均值作为纹理
LINEAR_MIPMAP_LINEAR, //使用线性均和计算两个纹理的值
LINEAR_MIPMAP_NEAREST, //线性地改写临近的纹理单元值
NEAREST, //取比较接近的像素作为纹理
NEAREST_MIPMAP_LINEAR, //在两个纹理中选择最临近的纹理,并取它们之间的线性均和值
NEAREST_MIPMAP_NEAREST //选择最临近的纹理单元值
};
*/
cubemap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
cubemap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
}
return cubemap.release();
}
osg::ref_ptr<osg::Node> createSkyBox()
{
//osg::ref_ptr<osg::Drawable> drawable = new osg::ShapeDrawable(new osg::Box(osg::Vec3(691940.61, 4871848.22, 236.13), 53.0, 45.0, 80.0)); //建筑物
//osg::ref_ptr<osg::Drawable> drawable = new osg::ShapeDrawable(new osg::Box(osg::Vec3(691940.61, 4871848.22, 236.13), 10.0, 10.0, 10.0)); //建筑物
osg::ref_ptr<osg::Drawable> drawable = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 10.0, 10.0, 10.0)); //建筑物
//设置立方图纹理
osg::ref_ptr<osg::TextureCubeMap> skymap = readCubeMap();
auto stateset = drawable->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, skymap, osg::StateAttribute::ON);
osg::ref_ptr<osg::TexGen> tg = new osg::TexGen();
tg->setMode(osg::TexGen::EYE_LINEAR);
tg->setPlane(osg::TexGen::S, osg::Plane(-1,0,0,0));
stateset->setTextureAttributeAndModes(0, tg, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
//把球体加入到叶节点
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
//geode->setCullingActive(false);
//geode->setStateSet(stateset.get());
geode->addDrawable(drawable.get());
return geode.release();
}
int main()
{
osg::ref_ptr<osg::Group> root = new osg::Group();
//加入天空盒
root->addChild(createSkyBox());
//优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
osgDB::writeNodeFile(*root, "F:/changchun/test3.osgb");
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
viewer->setSceneData(root.get());
viewer->realize();
return viewer->run();
}