OSG纹理贴图问题

时间:2021-03-29 16:12:40
osg::Drawable* createSquare(const osg::Vec3& corner,const osg::Vec3& width,const osg::Vec3& height, osg::Image* image=NULL)
{
osg::Geometry* geom = new osg::Geometry;

osg::Vec3Array* coords = new osg::Vec3Array(4);
(*coords)[0] = corner;
(*coords)[1] = corner+width;
(*coords)[2] = corner+width+height;
(*coords)[3] = corner+height;

geom->setVertexArray(coords);

osg::Vec3Array* norms = new osg::Vec3Array(1);
(*norms)[0] = width^height;
(*norms)[0].normalize();

geom->setNormalArray(norms);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

// 纹理坐标
osg::Vec2Array* tcoords = new osg::Vec2Array(4);
(*tcoords)[0].set(0.0f,0.0f);
(*tcoords)[1].set(1.0f,0.0f);
(*tcoords)[2].set(1.0f,1.0f);
(*tcoords)[3].set(0.0f,1.0f);
geom->setTexCoordArray(0,tcoords);

// 顶点索引
osg::UByteArray* coordIndices = new osg::UByteArray; // assumes we are using less than 256 points...

// 注意:4个顶点的顺序
coordIndices->push_back(0);
coordIndices->push_back(1);
coordIndices->push_back(2);
coordIndices->push_back(3);

geom->setVertexIndices(coordIndices);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coordIndices->size()));

if (image)
{
osg::StateSet* stateset = new osg::StateSet;
osg::Texture2D* texture = new osg::Texture2D;
texture->setImage(image);
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
geom->setStateSet(stateset);
}

return geom;
}

void cOSG::Test()
{
const osg::Vec3 corner( 0,0,0 );
const osg::Vec3 width( 1,0,0 );
const osg::Vec3 height( 0,1,0 );

osg::Image* image=NULL ;
image = osgDB::readImageFile("d:\\00_OSG\\dataTest\\000.jpg");

osg::Geode* geode = new osg::Geode;
geode->addDrawable(createSquare(corner, width, height, image));

mRootData->addChild(geode);
}

上面的代码绘制出来一个正确纹理的正方形,贴图正确,为什么就不能绘制多个正方形呢?替换为下面的代码,贴图不对啊?
OSG纹理贴图问题
osg::Drawable* createSquare(const osg::Vec3& corner,const osg::Vec3& width,const osg::Vec3& height, osg::Image* image=NULL)
{
osg::Geometry* geom = new osg::Geometry;
osg::Vec3Array* coords = new osg::Vec3Array( 9);
(*coords)[0] = corner;
(*coords)[1] = corner+width;
(*coords)[2] = corner+width+width;
(*coords)[3] = corner+height;
(*coords)[4] = corner+height+width;
(*coords)[5] = corner+height+width+width;
(*coords)[6] = corner+height+height;
(*coords)[7] = corner+height+height+width;
(*coords)[8] = corner+height+height+width+width;


geom->setVertexArray(coords);

osg::Vec3Array* norms = new osg::Vec3Array(1);
(*norms)[0] = width^height;
(*norms)[0].normalize();

geom->setNormalArray(norms);
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

// 纹理坐标
osg::Vec2Array* tcoords = new osg::Vec2Array(9);
(*tcoords)[0].set(0.0f,0.0f);
(*tcoords)[1].set(0.5f,0.0f);
(*tcoords)[2].set(1.0f,0.0f);
(*tcoords)[3].set(0.0f,0.5f);
(*tcoords)[4].set(0.5f,0.5f);
(*tcoords)[5].set(1.0f,0.5f);
(*tcoords)[6].set(0.0f,1.0f);
(*tcoords)[7].set(0.5f,1.0f);
(*tcoords)[8].set(1.0f,1.0f);


geom->setTexCoordArray(0,tcoords);

// 顶点索引
osg::UByteArray* coordIndices = new osg::UByteArray; 

// 注意:4个顶点的顺序
coordIndices->push_back(0);
coordIndices->push_back(1);
coordIndices->push_back(4);
coordIndices->push_back(3);


geom->setVertexIndices(coordIndices);

geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,coordIndices->size()));
//geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,coordIndices->size()));


if (image)
{
osg::StateSet* stateset = new osg::StateSet;
osg::Texture2D* texture = new osg::Texture2D;
texture->setImage(image);

texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);

stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
//stateset->setTextureAttributeAndModes(0, texture);

geom->setStateSet(stateset);
}

return geom;
}

2 个解决方案

#1


我也是深深的感到蛋疼,原来  纹理坐标 数目要和 索引数组一一对应,我用索引生成了一个正方形,所以,纹理应该是: 
(*tcoords)[0].set(0.0f,0.0f);
(*tcoords)[1].set(0.5f,0.0f);
(*tcoords)[2].set(0.5f,0.5f);
(*tcoords)[3].set(0.0f,0.5f);

和 
coordIndices->push_back(0);
coordIndices->push_back(1);
coordIndices->push_back(4);
coordIndices->push_back(3);
对应。问题解决。

不过,我理解,一个实体定点应该就一个纹理坐标,这样纹理不就有重复?

貌似我理解的不对,假如一个立方体,公用定点,但是三个面可能使用不同的纹理文件和不同的纹理坐标,那么,一个实体点就会有多个纹理坐标,所以,纹理坐标和索引数目一致是正确的。

#2


或者,使用纹理索引,让坐标索引和纹理索引使用同一个 索引表!!!

#1


我也是深深的感到蛋疼,原来  纹理坐标 数目要和 索引数组一一对应,我用索引生成了一个正方形,所以,纹理应该是: 
(*tcoords)[0].set(0.0f,0.0f);
(*tcoords)[1].set(0.5f,0.0f);
(*tcoords)[2].set(0.5f,0.5f);
(*tcoords)[3].set(0.0f,0.5f);

和 
coordIndices->push_back(0);
coordIndices->push_back(1);
coordIndices->push_back(4);
coordIndices->push_back(3);
对应。问题解决。

不过,我理解,一个实体定点应该就一个纹理坐标,这样纹理不就有重复?

貌似我理解的不对,假如一个立方体,公用定点,但是三个面可能使用不同的纹理文件和不同的纹理坐标,那么,一个实体点就会有多个纹理坐标,所以,纹理坐标和索引数目一致是正确的。

#2


或者,使用纹理索引,让坐标索引和纹理索引使用同一个 索引表!!!