Coin3d/OpenInventor中为SoIndexedFaceSet各面设置不同纹理的咨询
Coin3d/OpenInventor 为SoIndexedFaceSet每个面设置不同纹理的问题与解决
我用SoIndexedFaceSet创建了6个面,尝试用SoTexture3给每个面贴不同图片但失败了,求可行方案并排查代码问题。
原代码
SoSeparator* root = new SoSeparator; root->ref(); SoTransform* pTransfrom = new SoTransform; pTransfrom->translation.setValue(0, 0, 0); root->addChild(pTransfrom); SoMaterialBinding* faceBind = new SoMaterialBinding; faceBind->value = SoMaterialBinding::PER_PART; root->addChild(faceBind); SoTexture3* texture = new SoTexture3; texture->filenames.set1Value(0, SbString("D:/wrapper/TCom_Wall_Stone3_2x2_1K_albedo.tif")); texture->filenames.set1Value(1, SbString("D:/wrapper/Com_Wall_Stone3_2x2_1K_ao.tif")); texture->filenames.set1Value(2, SbString("D:/wrapper/TCom_Wall_Stone3_2x2_1K_height.tif")); texture->filenames.set1Value(3, SbString("D:/wrapper/TCom_Wall_Stone3_2x2_1K_normal.tif")); texture->filenames.set1Value(4, SbString("D:/wrapper/4.jpg")); texture->filenames.set1Value(5, SbString("D:/wrapper/5.jpg")); root->addChild(texture); SoCoordinate3* coordinates = new SoCoordinate3; //front coordinates->point.set1Value(0, 0, 0, 0); coordinates->point.set1Value(1, step, 0, 0); coordinates->point.set1Value(2, step, 0, step); coordinates->point.set1Value(3, 0, 0, step); //back coordinates->point.set1Value(4, step, step, 0); coordinates->point.set1Value(5, 0, step, 0); coordinates->point.set1Value(6, 0, step, step); coordinates->point.set1Value(7, step, step, step); root->addChild(coordinates); SoIndexedFaceSet* faceSet = new SoIndexedFaceSet; //front faceSet->coordIndex.set1Value(0, 0); faceSet->coordIndex.set1Value(1, 1); faceSet->coordIndex.set1Value(2, 2); faceSet->coordIndex.set1Value(3, 3); faceSet->coordIndex.set1Value(4, -1); //back faceSet->coordIndex.set1Value(5, 4); faceSet->coordIndex.set1Value(6, 5); faceSet->coordIndex.set1Value(7, 6); faceSet->coordIndex.set1Value(8, 7); faceSet->coordIndex.set1Value(9, -1); //left faceSet->coordIndex.set1Value(10, 5); faceSet->coordIndex.set1Value(11, 0); faceSet->coordIndex.set1Value(12, 3); faceSet->coordIndex.set1Value(13, 6); faceSet->coordIndex.set1Value(14, -1); //right faceSet->coordIndex.set1Value(15, 1); faceSet->coordIndex.set1Value(16, 4); faceSet->coordIndex.set1Value(17, 7); faceSet->coordIndex.set1Value(18, 2); faceSet->coordIndex.set1Value(19, -1); //top faceSet->coordIndex.set1Value(20, 3); faceSet->coordIndex.set1Value(21, 2); faceSet->coordIndex.set1Value(22, 7); faceSet->coordIndex.set1Value(23, 6); faceSet->coordIndex.set1Value(24, -1); //bottom faceSet->coordIndex.set1Value(25, 5); faceSet->coordIndex.set1Value(26, 4); faceSet->coordIndex.set1Value(27, 1); faceSet->coordIndex.set1Value(28, 0); faceSet->coordIndex.set1Value(29, -1); root->addChild(faceSet); setSceneGraph(root);
代码错误分析
- SoTexture3用错组件:SoTexture3是用于3D体纹理的,不是给多个面分配不同2D纹理的工具,应该用
SoTexture2加载多张2D图片。 - 绑定节点错误:
SoMaterialBinding是给材质属性用的,纹理绑定需要用SoTextureCoordinateBinding,并设置正确的绑定模式。 - 缺少纹理索引指定:没有通过
SoTextureIndex节点告诉每个面应该使用哪一张纹理。
修正方案
- 替换
SoTexture3为SoTexture2,保留多纹理文件名设置。 - 添加
SoTextureCoordinateBinding节点,设置绑定模式为PER_PART(对应每个面用-1分隔的结构)。 - 添加
SoTextureIndex节点,为每个面指定对应的纹理索引(0到5,对应加载的6张图)。 - 移除无关的
SoMaterialBinding节点(如果不需要多材质)。
修正后的代码
SoSeparator* root = new SoSeparator; root->ref(); SoTransform* pTransfrom = new SoTransform; pTransfrom->translation.setValue(0, 0, 0); root->addChild(pTransfrom); // 纹理绑定:指定每个part(面)使用单独纹理 SoTextureCoordinateBinding* texBind = new SoTextureCoordinateBinding; texBind->value = SoTextureCoordinateBinding::PER_PART; root->addChild(texBind); // 用SoTexture2加载多张2D纹理 SoTexture2* texture = new SoTexture2; texture->filenames.set1Value(0, SbString("D:/wrapper/TCom_Wall_Stone3_2x2_1K_albedo.tif")); texture->filenames.set1Value(1, SbString("D:/wrapper/Com_Wall_Stone3_2x2_1K_ao.tif")); texture->filenames.set1Value(2, SbString("D:/wrapper/TCom_Wall_Stone3_2x2_1K_height.tif")); texture->filenames.set1Value(3, SbString("D:/wrapper/TCom_Wall_Stone3_2x2_1K_normal.tif")); texture->filenames.set1Value(4, SbString("D:/wrapper/4.jpg")); texture->filenames.set1Value(5, SbString("D:/wrapper/5.jpg")); // 设置纹理混合模式为MODULATE,确保正确渲染 texture->model = SoTexture2::MODULATE; root->addChild(texture); // 为每个面指定纹理索引:6个面对应6个索引 SoTextureIndex* texIndex = new SoTextureIndex; texIndex->index.set1Value(0, 0); // 正面用第0张 texIndex->index.set1Value(1, 1); // 背面用第1张 texIndex->index.set1Value(2, 2); // 左面用第2张 texIndex->index.set1Value(3, 3); // 右面用第3张 texIndex->index.set1Value(4, 4); // 顶面用第4张 texIndex->index.set1Value(5, 5); // 底面用第5张 root->addChild(texIndex); SoCoordinate3* coordinates = new SoCoordinate3; //front coordinates->point.set1Value(0, 0, 0, 0); coordinates->point.set1Value(1, step, 0, 0); coordinates->point.set1Value(2, step, 0, step); coordinates->point.set1Value(3, 0, 0, step); //back coordinates->point.set1Value(4, step, step, 0); coordinates->point.set1Value(5, 0, step, 0); coordinates->point.set1Value(6, 0, step, step); coordinates->point.set1Value(7, step, step, step); root->addChild(coordinates); SoIndexedFaceSet* faceSet = new SoIndexedFaceSet; //front faceSet->coordIndex.set1Value(0, 0); faceSet->coordIndex.set1Value(1, 1); faceSet->coordIndex.set1Value(2, 2); faceSet->coordIndex.set1Value(3, 3); faceSet->coordIndex.set1Value(4, -1); //back faceSet->coordIndex.set1Value(5, 4); faceSet->coordIndex.set1Value(6, 5); faceSet->coordIndex.set1Value(7, 6); faceSet->coordIndex.set1Value(8, 7); faceSet->coordIndex.set1Value(9, -1); //left faceSet->coordIndex.set1Value(10, 5); faceSet->coordIndex.set1Value(11, 0); faceSet->coordIndex.set1Value(12, 3); faceSet->coordIndex.set1Value(13, 6); faceSet->coordIndex.set1Value(14, -1); //right faceSet->coordIndex.set1Value(15, 1); faceSet->coordIndex.set1Value(16, 4); faceSet->coordIndex.set1Value(17, 7); faceSet->coordIndex.set1Value(18, 2); faceSet->coordIndex.set1Value(19, -1); //top faceSet->coordIndex.set1Value(20, 3); faceSet->coordIndex.set1Value(21, 2); faceSet->coordIndex.set1Value(22, 7); faceSet->coordIndex.set1Value(23, 6); faceSet->coordIndex.set1Value(24, -1); //bottom faceSet->coordIndex.set1Value(25, 5); faceSet->coordIndex.set1Value(26, 4); faceSet->coordIndex.set1Value(27, 1); faceSet->coordIndex.set1Value(28, 0); faceSet->coordIndex.set1Value(29, -1); root->addChild(faceSet); setSceneGraph(root);
额外说明
- 如果纹理仍未正确显示,检查图片路径是否正确、文件是否损坏,Coin3d支持tif、jpg等常见格式。
- 也可以选择拆分方案:将每个面做成独立的
SoIndexedFaceSet,每个面单独添加SoTexture2节点,这种方式更直观,但节点数量会增加。
内容的提问来源于stack exchange,提问作者Z.Ju
相关产品推荐
相关产品推荐

