通过BRepMesh_IncrementalMesh得到OCC的Solid的各个Face的三角网格, 可以通过
TopLoc_Location loc;
Handle_Poly_Triangulation triFace = BRep_Tool::Triangulation(aFace, loc);
const TColgp_Array1OfPnt2d& uvNodes = triFace->UVNodes();
得到三角网格顶点的每个uv坐标,但是这个uv坐标其实是aFace的曲面方程的自变量F(u,v),如果将这个值设置给OSG,Ogre或者OpenGL
的纹理坐标,一般显示的曲面是扭曲的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQpZA9Rw-1722128179703)(https://i-blog.csdnimg.cn/direct/358e73ea46f3403296f9d3f531c316af.png)]
下面计算曲面的纹理使得均匀贴敷,要通过uv算点Vi在曲面曲纹坐标网上的实际的u_s, v_s
经常matplot画的曲面上的黑色的网格就是曲纹坐标网
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajz23Pma-1722128179705)(https://i-blog.csdnimg.cn/direct/420f124456014f4c874ec7642eae202e.png)]
const TColgp_Array1OfPnt2d& uvNodes = triFace->UVNodes();
int nNodes = aFace的顶点个数
for (Standard_Integer i = 1; i <= nNodes; i++)
{
gp_Pnt2d uv = uvNodes.Value(i); // 得到顶点Vi的uv
float unitscale = 0.1; // 单位缩放, 纹理尺寸和曲面尺度比例
if (adasurf.GetType() == GeomAbs_SurfaceType::GeomAbs_Plane) // 如果是平面就用uv做纹理坐标
{
vertUVs->push_back(osg::Vec2(uv.X() * unitscale, uv.Y() * unitscale));
}
else // 否则计算Vi的两条曲面上的
{
// 得到u值(或者v值)固定的沿着v(或u)走势的曲面上的曲线, 计算出曲面上相对原点的路径u_s和v_s
// 作为纹理
auto ucurve = adasurf.Surface().Surface()->UIso(uv.X());
GeomAdaptor_Curve adacurve_u(ucurve);
double v_s = CPnts_AbscissaPoint::Length(adacurve_u, 0.0, uv.Y());
auto vcurve = adasurf.Surface().Surface()->VIso(uv.Y());
GeomAdaptor_Curve adacurve_v(vcurve);
double u_s = CPnts_AbscissaPoint::Length(adacurve_v, 0.0, uv.X());
vertUVs->push_back(osg::Vec2(u_s * unitscale, v_s * unitscale));
}
这样结果就是正确了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RozYlvWC-1722128179706)(https://i-blog.csdnimg.cn/direct/1bda21a7a6794940875fb09b2a56a1a4.png)]
说明:圆柱体的纹理看起来“均匀”,是因为圆柱曲面参数方程是:
f_x(u, v)=rcos(u)
f_y(u, v)=rsin(u)
f_z(u, v)=v
所以如果纹理直接用u,它的取值范围是[0.0,2PI]
贴出来就感觉圆周方向纹理被收缩了,所以它的UIso曲线是个圆,这样就得到了实际的us,相当于us=ur
其它二次曲面纹理要铺成什么样子要具体分析,例如圆环曲面tour有两个半径它的us=Ru vs=r*v