沿着三维曲线渲染圆形

4
我正在尝试在3D曲线的每个点周围渲染圆圈。基本上是为曲线创建管状结构。但是,如图所示,圆的方向是错误的。下面是在计算弗雷内框架后圆对象的模型矩阵计算。我错在哪里了? 参考资料,绿线是切线,蓝线是法线,红线是副法线。

view 1 view 2

Frenet Frame Calculations

glm::vec3 pointback = curve_points[i-1];
glm::vec3 pointmid = curve_points[i];
glm::vec3 pointforward = curve_points[i+1];

glm::vec3 forward_tangent_vector =  glm::vec3(glm::normalize(pointforward - pointmid)) ;
glm::vec3 backward_tangent_vector = glm::vec3(glm::normalize(pointmid - pointback)) ;

glm::vec3 second_order_tangent = glm::normalize(forward_tangent_vector - backward_tangent_vector);

glm::vec3 binormal = glm::normalize(glm::cross(forward_tangent_vector, second_order_tangent));

glm::vec3 normal = glm::normalize(glm::cross(binormal, forward_tangent_vector));

用于圆形计算的模型矩阵

glm::mat3 tbn = glm::mat3(forward_tangent_vector,binormal,normal);

glm::vec3 normal_axis = glm::vec3(0, 1, 0);
//normal_axis = forward_tangent_vector;

glm::vec3 circleNormal = glm::normalize(tbn * normal_axis);
glm::vec3 rotationAxis = glm::cross(normal_axis, circleNormal);
float rotationAngle = glm::acos(glm::dot(normal_axis, circleNormal));

R = glm::rotate(R, glm::degrees(rotationAngle), rotationAxis);

T = glm::translate(T, pointmid);

glm::mat4 Model = T*R;

2
圆必须由法向量和副法向量构建。 - user1196549
目前看起来它们是由切向量和法向量构建的。 - user1196549
目前它们是在循环中使用以下代码构建的: float x = 0.1f*cos(dt * i); float y = 0.f; float z = 0.1f*sin(dt * i); - jaykumarark
1
然后交换两个坐标。 - user1196549
搞定了!非常感谢! - jaykumarark
显示剩余3条评论
1个回答

5
最简单的方法是使用弗雷内-塞雷特坐标系,通常称为TBN坐标系或TBN矩阵。方法如下:
  1. Sample two points on the curve. Let's call them "current" and "next".
  2. Construct the Frenet frame as follows:

    vec3 T = normalize( next - current );
    vec3 B = normalize( cross( T, next + current ) );
    vec3 N = normalize( cross( B, T ) );
    
  3. Calculate your 2D circle, similar to this:

    float x = cos( angle );
    float y = sin( angle );
    
  4. Now, use the Frenet frame to calculate the proper orientation:

    vec3 tangent = T;
    vec3 normal = normalize( B * x + N * y );
    vec3 vertex = current + B * x + N * y; // note: not normalized!
    
您可以在这里找到易于理解的解释:http://www.blackpawn.com/texts/pqtorus/

1
谢谢!您的解释和附带的链接非常好!这正是我需要更好地理解这个问题的数学。 - jaykumarark
1
如果您有一个分析曲线,无论是样条曲线还是其他类型的数学函数,我认为最好通过分析计算方向向量。取两点之间的差只是一种近似方法。如果您有曲线的参数表示,则方向向量仅由坐标的参数函数的导数给出。 - Reto Koradi
@RetoKoradi:你说的分析解更精确是对的,但我认为它不一定更好。例如,如果你正在构建一个网格并想要对其应用法线映射着色器,你会希望切线沿着表面运行。本文中的算法将确保这一点。更精确的切线和法线对于光照计算来说不会产生很大的视觉差异,但可能会出现法线映射伪影。因此,使用分析方法是否更好取决于你的用例。 - Paul Houx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接