OpenCasCade – 贴纹理
前言
因为项目需要,所以最近研究了下给 用OpenCasCade库创建的模型贴纹理的问题。因为网上没找到相关的文章,特此记录下来。
官方示例
本文中的代码是完全仿照官方示例(All-vc10 中的 Viewer3d)所写的,筒子们可以自己去研究一下这块代码,如图:
然后看下官方示例的贴纹理效果:
代码解读
这里为简单起见,只解读图一中 Bottle 的代码, 代码的作用,请仔细阅读注释:
sampleBottle函数(创建Bottle,调用Texturize函数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
//通过载入brep文件,创建bottle,并贴纹理 void TexturesExt_Presentation::sampleBottle() { //创建一个bottle TopoDS_Shape aShape; if (!loadShape(aShape, "bottle.brep")) return;
// resize and move the shape to the center of the viewer 这块代码对纹理显示无贡献 gp_Trsf aTrsf1, aTrsf2; aTrsf1.SetScale(gp_Pnt(0,0,0), /*0.8*/0.1); //对 bottle 进行缩放 aTrsf2.SetTranslation(gp_Pnt(0,0,0),gp_Pnt(0,0,-20)); aTrsf1.Multiply(aTrsf2); BRepBuilderAPI_Transform Transformer(aTrsf1); Transformer.Perform(aShape); aShape = Transformer.Shape();
TopTools_IndexedMapOfShape aFaces; // 函数原型:static void TopExp::MapShapes(const TopoDS_Shape& S, const TopAbs_ShapeEnum T, TopTools_IndexedMapOfShape& M) // 第二个参数: TopAbs_ShapeEnum 是一个枚举类型,读者需要自己去读一下 // Tool to explore a topological data structure. Stores in the map <M> all the sub-shapes of <S> of type <T>. TopExp::MapShapes(aShape, TopAbs_FACE, aFaces);
//没有这几句代码 则只显示指定贴了纹理的那些FACE,不显示瓶子整体。但同样,这段对纹理的显示没有任何贡献。 //display original shape in shaded display mode Handle_AIS_Shape aShapeIO = drawShape(aShape, Graphic3d_NOM_BRASS, Standard_False); getAISContext()->SetDisplayMode(aShapeIO, AIS_Shaded, Standard_False); // Set increased polygon offset for the main shape to avoid depth collision with textured faces aShapeIO->SetPolygonOffsets(Aspect_POM_Fill, 1.5, 0.5); DISP(aShapeIO); // #define DISP(OBJ) getAISContext()->Display((OBJ), Standard_False)
//指定需要贴纹理的FACE,设置相关参数 Handle_AIS_TexturedShape aTFace1 = Texturize(aFaces(16), "carrelage1.gif", 1, 1, 3, 2); DISP(aTFace1);
Handle_AIS_TexturedShape aTFace2 = Texturize(aFaces(21), "carrelage1.gif", 1, 1, 3, 2); DISP(aTFace2);
//更新视图 getViewer()->Update(); } |
Texturize函数(贴纹理):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
Handle_AIS_TexturedShape TexturesExt_Presentation::Texturize(const TopoDS_Shape& aShape, TCollection_AsciiString aTFileName, Standard_Real toScaleU, Standard_Real toScaleV, Standard_Real toRepeatU, Standard_Real toRepeatV, Standard_Real originU, Standard_Real originV) { //create a textured presentation object for aShape //AIS_TexturedShape 是一个非常重要的类!下面是官方文档中的说明 //This class allows to map textures on shapes. Presentations modes AIS_WireFrame (0) and AIS_Shaded (1) behave in the same manner as in AIS_Shape //whilst new modes 2 (bounding box) and 3 (texture mapping) extends it functionality. //The texture itself is parametrized in (0,1)x(0,1). Each face of a shape located in UV space is provided with these parameters: //•Umin - starting position in U //•Umax - ending position in U //•Vmin - starting position in V //•Vmax - ending position in V //Each face is triangulated and a texel is assigned to each node. Facets are then filled using a linear interpolation of texture between each 'three texels'. //User can act on: //•the number of occurrences of the texture on the face //•the position of the origin of the texture //•the scale factor of the texture Handle_AIS_TexturedShape aTShape = new AIS_TexturedShape(aShape);
TCollection_AsciiString TFileName;
//load texture from file if it is not an integer value //integer value indicates a number of texture in predefined TexturesExt enumeration CString initfile(((OCC_App*) AfxGetApp())->GetInitDataDir()); initfile += "\\Data\\"; if (!aTFileName.IsIntegerValue()) { initfile += aTFileName.ToCString(); }
aTShape->SetTextureFileName((Standard_CString)(LPCTSTR)initfile);
// do other initialization of AIS_TexturedShape aTShape->SetTextureMapOn(); aTShape->SetTextureScale(Standard_True, toScaleU, toScaleV); aTShape->SetTextureRepeat(Standard_True, toRepeatU, toRepeatV); aTShape->SetTextureOrigin(Standard_True, originU, originV);
aTShape->SetDisplayMode(3); // mode 3 is "textured" mode,参见上面AIS_TexturedShape类的解释
return aTShape; } |
至此,就可以实现上图中显示的Bottle效果。同学们可以自己创建一个简单的 box 来尝试一下,这里我给个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void CneedAVView::MakeBottle() { TopoDS_Shape aRes = BRepPrimAPI_MakeBox(gp_Pnt(0,0,0),555,555,555).Shape(); TopTools_IndexedMapOfShape aFaces; TopExp::MapShapes(aRes, TopAbs_FACE, aFaces); Handle(AIS_TexturedShape) aTFace1 = Texturize(aFaces(1), "./carrelage1.gif", 1, 1, 3, 2); DISP(aTFace1);
Handle(AIS_TexturedShape) aTFace2 = Texturize(aFaces(2), "./carrelage1.gif", 1, 1, 3, 2); //16 21 3 2 DISP(aTFace2);
Handle(AIS_TexturedShape) aTFace5 = Texturize(aFaces(5), "./carrelage1.gif", 1, 1, 3, 2); DISP(aTFace5);
myView->Update(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Handle(AIS_TexturedShape) CneedAVView::Texturize(const TopoDS_Shape& aShape, TCollection_AsciiString aTFileName, Standard_Real toScaleU, Standard_Real toScaleV, Standard_Real toRepeatU, Standard_Real toRepeatV, Standard_Real originU, Standard_Real originV) { // create a textured presentation object for aShape Handle(AIS_TexturedShape) aTShape = new AIS_TexturedShape(aShape);
//此地纯属偷懒 CString temp("d://program files//opencascade-6.7.1//samples//mfc//standard//04_viewer3d//data//cookerplate.gif"); aTShape->SetTextureFileName((Standard_CString)(LPCTSTR)temp);
// do other initialization of AIS_TexturedShape aTShape->SetTextureMapOn(); aTShape->SetTextureScale(Standard_True, toScaleU, toScaleV); aTShape->SetTextureRepeat(Standard_True, toRepeatU, toRepeatV); aTShape->SetTextureOrigin(Standard_True, originU, originV);
aTShape->SetDisplayMode(3); // mode 3 is "textured" mode
return aTShape; } |
也许你发现这样还是看不到显示的纹理!
后来发现,需要设置这样关键的一句
1 |
myView->SetSurfaceDetail(V3d_TEX_ALL); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
函数原型:void V3d_View::SetSurfaceDetail(const V3d_TypeOfSurfaceDetail SurfaceDetail) 功 能:select the kind of rendering for texture mapping no texture mapping by default
其中 V3d_TypeOfSurfaceDetail 是一个枚举类 enum V3d_TypeOfSurfaceDetail Modes of visualization for objects in a view. ·V3d_TEX_NONE: no texture mapping, ·V3d_TEX_ENVIRONMENT: environment mapping only, ·V3d_TEX_ALL: environment and texture mapping.
Enumerator: ·V3d_TEX_NONE ·V3d_TEX_ENVIRONMENT ·V3d_TEX_ALL |
如官方文档中所述:
1 |
no texture mapping by default |
所以我们要显示的把参数设置为:V3d_TEX_ALL
如此,你就可以看到自己贴的纹理了,效果图如下(因为我省略了一些函数所以这里只显示了贴纹理的面(见 sampleBottle 函数中所述)):
至此,OpenCasCade的中的贴纹理就搞定了,想了解更多,请自行阅读官方示例。
感谢原作者的知识分享。