Reputation: 2449
I am trying to render circles around each point of a 3d curves. Basically trying to create a tube like structure for the curve. But the orientation of the circle is wrong as shown in the image. Below are my calculations for the Model matrix of the circle object after calculating the frenet frame. Where am I going wrong? For reference, green line is the tangent, blue is the normal and red is the binormal.
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));
Model Matrix for Circle calculations
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;
Upvotes: 4
Views: 1166
Reputation: 2043
The easiest way to do this is by using Frenet-Serret frames, more commonly known as TBN frames or a TBN matrix. Here's how:
Construct the Frenet frame as follows:
vec3 T = normalize( next - current );
vec3 B = normalize( cross( T, next + current ) );
vec3 N = normalize( cross( B, T ) );
Calculate your 2D circle, similar to this:
float x = cos( angle );
float y = sin( angle );
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!
An easy to follow explanation can be found here: http://www.blackpawn.com/texts/pqtorus/
Upvotes: 5