用c++表达 Frenet frame

数学描述

The formulas given above for TN, and B depend on the curve being given in terms of the arclength parameter. This is a natural assumption in Euclidean geometry, because the arclength is a Euclidean invariant of the curve. In the terminology of physics, the arclength parametrization is a natural choice of gauge. However, it may be awkward to work with in practice. A number of other equivalent expressions are available.

Suppose that the curve is given by r(t), where the parameter t need no longer be arclength. Then the unit tangent vector T may be written as

\mathbf{T}(t) = \frac{\mathbf{r}'(t)}{\|\mathbf{r}'(t)\|}.

The normal vector N takes the form

\mathbf{N}(t) = \frac{\mathbf{T}'(t)}{\|\mathbf{T}'(t)\|} = \frac{\mathbf{r}'(t) \times \left(\mathbf{r}''(t) \times \mathbf{r}'(t) \right)}{\left\|\mathbf{r}'(t)\right\| \, \left\|\mathbf{r}''(t) \times \mathbf{r}'(t)\right\|}.

The binormal B is then

'(t)\times \mathbf {r} ''(t)\|}}.}\mathbf{B}(t) = \mathbf{T}(t)\times\mathbf{N}(t) = \frac{\mathbf{r}'(t)\times\mathbf{r}''(t)}{\|\mathbf{r}'(t)\times\mathbf{r}''(t)\|}.

An alternative way to arrive at the same expressions is to take the first three derivatives of the curve r′(t), r′′(t), r′′′(t), and to apply the Gram-Schmidt process. The resulting ordered orthonormal basis is precisely the TNB frame. This procedure also generalizes to produce Frenet frames in higher dimensions.

In terms of the parameter t, the Frenet–Serret formulas pick up an additional factor of ||r′(t)|| because of the chain rule:

\frac{d}{dt} \begin{bmatrix} \mathbf{T}\\ \mathbf{N}\\ \mathbf{B} \end{bmatrix} = \|\mathbf{r}'(t)\| \begin{bmatrix} 0&\kappa&0\\ -\kappa&0&\tau\\ 0&-\tau&0 \end{bmatrix} \begin{bmatrix} \mathbf{T}\\ \mathbf{N}\\ \mathbf{B} \end{bmatrix}.

Explicit expressions for the curvature and torsion may be computed. For example,

\kappa = \frac{\|\mathbf{r}'(t)\times\mathbf{r}''(t)\|}{\|\mathbf{r}'(t)\|^3}.

The torsion may be expressed using a scalar triple product as follows,

\tau = \frac{[\mathbf{r}'(t),\mathbf{r}''(t),\mathbf{r}'''(t)]}{\|\mathbf{r}'(t)\times\mathbf{r}''(t)\|^2}.

 

// 其他描述

1) For a given point P0, calculate the tangent vector T0.

One simple, easy way, is to take next point on the curve, subtract current point, then normalize result :

T0 = normalize(P1 - P0)

Another, more precise way, to get tangent is to calculate the derivative of your bezier curve function.

Then, pick an arbitrary vector V (for example, you can use (0, 0, 1))

Make N0 = crossproduct(T0, V) and B0 = crossproduct(T0, N0) (dont forget to normalize result vectors after each operation)

You now have a starting set of coordinates ( P0, B0, T0, N0)

enter image description here

This is the initial camera orientation.

2) Then, to calculate next points and their orientation :

Calculate T1 using same method as T0

Here is the trick, new reference frame is calculated from previous frame :

N1 = crossproduct(B0, T1)

B1 = crossproduct(T1, N1)

enter image description here

Proceed using same method for other points. It will results of having camera slightly rotating around tangent vector depending on how curve change its direction. Loopings will be handled correctly (camera wont twist like in my previous answer)

 

或者一个近似的表达

We can approximate T by finding a point a little farther ahead on the curve and subtracting our current position from it.

Since our curve is centered about the origin, we can approximate N with the bit of trickery shown in this picture. Here P is our current position on the curve and P' is a little farther ahead. The green line between P and P' is T. To get N we first add P and P' giving us a vector not perpendicular to T, but at least in the same plane. We then take the cross product of T and N to get B (it points out of the page) and take the cross product of B and T to get a better N (N' in the picture).

 

N and B need to be normalized before use, but we don't have to worry about T since we won't be using it. Assuming you defined your shape in the x-y plane here's how to orient it with the Frenet frame we just made:

 

或者 用opengl

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));
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值