C++ 沿三维曲线渲染圆

C++ 沿三维曲线渲染圆,c++,opengl,computational-geometry,curve,glm-math,C++,Opengl,Computational Geometry,Curve,Glm Math,我试图在3d曲线的每个点周围渲染圆。基本上尝试为曲线创建管状结构。但如图所示,圆的方向是错误的。下面是我在计算frenet帧后对圆形对象模型矩阵的计算。我哪里做错了? 作为参考,绿线是切线,蓝色是法线,红色是副法线 Frenet帧计算: glm::vec3 pointback = curve_points[i-1]; glm::vec3 pointmid = curve_points[i]; glm::vec3 pointforward = curve_points[i+1]; glm::

我试图在3d曲线的每个点周围渲染圆。基本上尝试为曲线创建管状结构。但如图所示,圆的方向是错误的。下面是我在计算frenet帧后对圆形对象模型矩阵的计算。我哪里做错了? 作为参考,绿线是切线,蓝色是法线,红色是副法线

Frenet帧计算

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;

最简单的方法是使用Frenet-Serret帧,通常称为TBN帧或TBN矩阵。以下是方法:

  • 对曲线上的两个点进行采样。让我们称之为“当前”和“下一步”
  • 按如下方式构造Frenet框架:

    vec3 T = normalize( next - current );
    vec3 B = normalize( cross( T, next + current ) );
    vec3 N = normalize( cross( B, T ) );
    
  • 计算二维圆,如下所示:

    float x = cos( angle );
    float y = sin( angle );
    
  • 现在,使用Frenet框架计算正确的方向:

    vec3 tangent = T;
    vec3 normal = normalize( B * x + N * y );
    vec3 vertex = current + B * x + N * y; // note: not normalized!
    
  • 以下是一个易于理解的解释:

    这些圆必须由法线和副法线向量构成。我不确定我是否在跟踪你。你能详细说明一下吗?看起来它们目前是从切线和法向量构建的。目前它们是在循环中使用这个来构建的
    float x=0.1f*cos(dt*i)浮动y=0.f
    float z=0.1f*sin(dt*i)然后交换两个坐标。谢谢!你的解释和附带的链接都很棒!如果你有一条解析曲线,不管是样条曲线还是其他数学函数,我认为用解析方法计算方向向量更好。取两点之间的差只是一个近似值。如果你有曲线的参数表示,方向向量只是由坐标的参数函数的导数给出。@RetoKoradi:你是对的,解析解更精确,但我认为它不一定更好。例如,如果要构造网格,并希望对其应用法线贴图着色器,则希望切线沿曲面运行。本文中的算法将确保这种情况。更精确的切线和法线不会对照明计算产生巨大的视觉差异,但您可能会看到法线贴图瑕疵。因此,分析方法是否更好取决于您的用例。