我正在尝试将2d形状轮廓附加到样条曲线。在样条曲线的某些点处,我会在几何体中看到奇怪的扭曲瑕疵,如图所示。如何使用Frenet-Frame方程避免这种情况?
我目前正常,正常和切线的计算:
forward_tangent_vector = glm::normalize(pointforward - pointmid);
backward_tangent_vector = glm::normalize(pointmid - pointback);
second_order_tangent = glm::normalize(forward_tangent_vector - backward_tangent_vector);
binormal = glm::normalize(glm::cross(forward_tangent_vector,second_order_tangent));
normal = glm::normalize(glm::cross(binormal, forward_tangent_vector));
//translation matrix
T = glm::translate(T, pointmid);
normal_axis = glm::vec3(0, 1, 0);
rotationAxis = glm::cross(normal_axis, forward_tangent_vector);
rotationAngle = glm::acos(glm::dot(normal_axis, forward_tangent_vector));
//rotation matrix
R = glm::rotate(R, glm::degrees(rotationAngle), rotationAxis);
答案 0 :(得分:3)
你成了hairy ball theorem的受害者:
计算机图形学中的一个常见问题是在R3中生成与给定的非零矢量正交的非零矢量。对于所有非零矢量输入,没有单个连续函数可以执行此操作。这是毛球定理的必然结果。要看到这一点,请将给定的向量视为球体的半径,并注意找到与给定向量正交的非零向量等效于找到与该球体表面相切的非零向量。半径。然而,毛球定理说没有连续函数可以对球体上的每个点(即每个给定的矢量)执行此操作。
另见:http://blog.sigfpe.com/2006/10/oriented-fish-and-hairy-balls.html
问题在于以下两点:
normal_axis = glm::vec3(0, 1, 0);
rotationAxis = glm::cross(normal_axis, forward_tangent_vector);
当forward_tangent_vector
与(0,1,0)
共线时,rotationAxis
变为(0,0,0)
。这就是为什么你的管道发生颠簸的原因。
你需要做的而不是硬编码(0,1,0)
,是取样条的一阶导数(速度/切线向量),取样条的二阶导数(加速度/法线向量),然后取交叉产品(binormal)。归一化这三个向量,你得到所谓的Frenet-frame,一组围绕样条的3个相互垂直的向量。
请注意,您的样条曲线必须是C2连续的,否则您会得到类似的"曲折"由二阶导数(即加速度/法向量)中的不连续性引起的。
一旦拥有了Frenet框架,就可以在该坐标系统中简单地改变基础。不要混淆glm::rotate
,只需将x,y,z单位向量放入矩阵中作为行(或列?我不确定GLM使用的约定......)和那个& #39;将成为你的变换矩阵。