C++ 多变量hermite样条
我知道如何做从(即4x4网格)像B样条曲线,卡特穆尔-Rom,贝塞尔 然而,我更希望类似2D/3D的类比由4个控制点(C++ 多变量hermite样条,c++,3d,interpolation,spline,hermite,C++,3d,Interpolation,Spline,Hermite,我知道如何做从(即4x4网格)像B样条曲线,卡特穆尔-Rom,贝塞尔 然而,我更希望类似2D/3D的类比由4个控制点(p00、p01、p10、p11)和4个法线(n00、n01、n10、n11)在该点进行描述 我试着编程(首先沿u进行2x1d插值,然后沿v插值结果) 当我意识到我不知道如何使用曲面法线来代替1D Hermite样条曲线中使用的导数时,我陷入了困境 如果我天真地只插入法线而不是导数,我会得到无意义的结果。在这里看到C++代码(我只使用相关部分): //基函数 模板 内联空心样条曲线
p00、p01、p10、p11
)和4个法线(n00、n01、n10、n11
)在该点进行描述
我试着编程(首先沿u
进行2x1d插值,然后沿v
插值结果)
当我意识到我不知道如何使用曲面法线来代替1D Hermite样条曲线中使用的导数时,我陷入了困境
如果我天真地只插入法线而不是导数,我会得到无意义的结果。在这里看到C++代码(我只使用相关部分):
//基函数
模板
内联空心样条曲线\u hermite\u基准(x型、c0型、c1型、d0型、d1型){
x2型=x*x;
x3型=x*x2;
c0=2*x3-3*x2+1;
c1=-2*x3+3*x2;
d0=x3-2*x2+x;
d1=x3-x2;
};
//基函数的导数
模板
内联空心样条线(x型、c0型、c1型、d0型、d1型){
x2型=x*x;
c0=6*x2-6*x;
c1=-6*x2+6*x;
d0=3*x2-4*x+1;
d1=3*x2-2*x;
};
无效立方体匹配点(双u、双v、,
const Vec3d和p00,const Vec3d和p01,const Vec3d和p10,const Vec3d和p11,
const Vec3d&n00、const Vec3d&n01、const Vec3d&n10、const Vec3d&n11、,
Vec3d&p、Vec3d&n
){
双cc0,cc1,cd0,cd1;
双dc0,dc1,dd0,dd1;
//沿u轴插值
样条hermite基(u,cc0,cc1,cd0,cd1);
dspline_hermite_基(u,dc0,dc1,dd0,dd1);
Vec3d p0u、p1u、n0u、n1u;
p0u.set_mul(p00,cc0);p0u.add_mul(p01,cc1);p0u.add_mul(n00,cd0);p0u.add_mul(n01,cd1);//p0u=cc0*p00+cc1*p01+cd0*n00+cd1*n01;
n0u.set_mul(p00,dc0);n0u.add_mul(p01,dc1);n0u.add_mul(n00,dd0);n0u.add_mul(n01,dd1);//n0u=dc0*p00+dc1*p01+dd0*n00+dd1*n01;
p1u.set_mul(p10,cc0);p1u.add_mul(p11,cc1);p1u.add_mul(n10,cd0);p1u.add_mul(n11,cd1);//p1u=cc0*p10+cc1*p11+cd0*n10+cd1*n11;
n1u.set_mul(p10,dc0);n1u.add_mul(p11,dc1);n1u.add_mul(n10,dd0);n1u.add_mul(n11,dd1);//n1u=dc0*p10+dc1*p11+dd0*n10+dd1*n11;
//沿v的插值
样条hermite基(v,cc0,cc1,cd0,cd1);
dspline_hermite_基(v,dc0,dc1,dd0,dd1);
p、 设置_mul(p0u,cc0);p.add_mul(p1u,cc1);p.add_mul(n0u,cd0);p.add_mul(n1u,cd1);//p=cc0*p0u+cc1*p1u+cd0*n0u+cd1*n1u;
n、 设置多个(p0u,dc0);n.add多个(p1u,dc1);n.add多个(n0u,dd0);n.add多个(n1u,dd1);//n=dc0*p0u+dc1*p1u+dd0*n0u+dd1*n1u;
}
您想要的是双三次Hermite曲面,它由4个角点和每个角点处的dS/du、dS/dv和d2S/dudv定义,其中dS/du和dS/dv是u和v方向上的偏导数,d2S/dudv是扭曲向量。有关更多详细信息,请参阅和
仅具有4个角点和4个法向量不足以唯一定义双三次曲面。但是,可以从法向量和4个角点推断dS/du和dS/dv。当然,推断公式需要确保dS/du和dS/dv之间的叉积向量与法向量方向相同。对于扭曲向量d2S/dudv,可以使用零向量。谢谢。与此同时,我发现这可能是问题所在(点和法线根本没有足够的自由度)。我有点失望,因为要扩展到更高的维度,任何三次插值都需要内存中4^N的数字,而不是2*(2^N)。。。如果我在trinagle(单纯形)而不是矩形上进行插值,会有什么变化吗?我的意思是:如果在trinagle上有类似hermite样条的东西,或者如果在三角形网格上有一个二维插值,并且有连续的导数,你只提供点和法线?
// basis function
template <class TYPE>
inline void spline_hermite_basis( TYPE x, TYPE& c0, TYPE& c1, TYPE& d0, TYPE& d1 ){
TYPE x2 = x*x;
TYPE x3 = x*x2;
c0 = 2*x3 - 3*x2 + 1;
c1 = -2*x3 + 3*x2 ;
d0 = x3 - 2*x2 + x;
d1 = x3 - x2 ;
};
// derivative of basis functions
template <class TYPE>
inline void dspline_hermite_basis( TYPE x, TYPE& c0, TYPE& c1, TYPE& d0, TYPE& d1 ){
TYPE x2 = x*x;
c0 = 6*x2 - 6*x ;
c1 = -6*x2 + 6*x ;
d0 = 3*x2 - 4*x + 1;
d1 = 3*x2 - 2*x ;
};
void cubicPatch_point( double u, double v,
const Vec3d& p00, const Vec3d& p01, const Vec3d& p10, const Vec3d& p11,
const Vec3d& n00, const Vec3d& n01, const Vec3d& n10, const Vec3d& n11,
Vec3d& p, Vec3d& n
){
double cc0,cc1,cd0,cd1;
double dc0,dc1,dd0,dd1;
// interpolation along u
spline_hermite_basis<double>( u, cc0, cc1, cd0, cd1 );
dspline_hermite_basis<double>( u, dc0, dc1, dd0, dd1 );
Vec3d p0u,p1u,n0u,n1u;
p0u.set_mul( p00, cc0 ); p0u.add_mul( p01, cc1 ); p0u.add_mul( n00, cd0 ); p0u.add_mul( n01, cd1 ); // p0u = cc0*p00 + cc1*p01 + cd0*n00 + cd1*n01;
n0u.set_mul( p00, dc0 ); n0u.add_mul( p01, dc1 ); n0u.add_mul( n00, dd0 ); n0u.add_mul( n01, dd1 ); // n0u = dc0*p00 + dc1*p01 + dd0*n00 + dd1*n01;
p1u.set_mul( p10, cc0 ); p1u.add_mul( p11, cc1 ); p1u.add_mul( n10, cd0 ); p1u.add_mul( n11, cd1 ); // p1u = cc0*p10 + cc1*p11 + cd0*n10 + cd1*n11;
n1u.set_mul( p10, dc0 ); n1u.add_mul( p11, dc1 ); n1u.add_mul( n10, dd0 ); n1u.add_mul( n11, dd1 ); // n1u = dc0*p10 + dc1*p11 + dd0*n10 + dd1*n11;
// interpolation along v
spline_hermite_basis<double>( v, cc0, cc1, cd0, cd1 );
dspline_hermite_basis<double>( v, dc0, dc1, dd0, dd1 );
p.set_mul( p0u, cc0 ); p.add_mul( p1u, cc1 ); p.add_mul( n0u, cd0 ); p.add_mul( n1u, cd1 ); // p = cc0*p0u + cc1*p1u + cd0*n0u + cd1*n1u;
n.set_mul( p0u, dc0 ); n.add_mul( p1u, dc1 ); n.add_mul( n0u, dd0 ); n.add_mul( n1u, dd1 ); // n = dc0*p0u + dc1*p1u + dd0*n0u + dd1*n1u;
}