gpt4 book ai didi

c++ - 多变量埃尔米特样条

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:17:15 24 4
gpt4 key购买 nike

我知道怎么做bicubic patch来自 16 control points (即 4x4 网格)如 B 样条、Catmull–Rom、Besier ...

但是,我更喜欢类似于 Hermite spline 的 2D/3D 类比。在这些点上由 4 个控制点 (p00,p01,p10,p11) 和 4 个法线 (n00,n01,n10,n11) 描述。

我尝试对其进行编程(首先沿 u 进行 2x 1D 插值,然后沿 v 进行插值)。

当我意识到我不知道如何使用表面法线而不是 1D Hermite 样条中使用的导数时,我陷入了困境。

如果我天真地只插入法线而不是导数,我会得到毫无意义的结果。请在此处查看 C++ 代码(我只使用了相关部分):

// 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;
}

最佳答案

你想要的是双三次 Hermite 曲面,它由 4 个角点和每个角点处的 dS/du、dS/dv 和 d2S/dudv 定义,其中 dS/du 和 dS/dv 是 u 的偏导数v 方向和 d2S/dudv 是扭曲 vector 。可以引用link1link2获取更多详细信息。

只有 4 个角点和 4 个法 vector 不足以唯一地定义双三次曲面。但是,您可以从法 vector 和 4 个角点推断出 dS/du 和 dS/dv。当然,推理公式需要保证dS/du与dS/dv的叉积 vector 与法 vector 方向一致。对于扭曲 vector d2S/dudv,可以使用零 vector 。

关于c++ - 多变量埃尔米特样条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31796717/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com