computeFrenetFrames method
dynamic
computeFrenetFrames(
- dynamic segments,
- dynamic closed
Implementation
computeFrenetFrames(segments, closed) {
// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
var normal = Vector3();
var tangents = [];
var normals = [];
var binormals = [];
var vec = Vector3();
var mat = Matrix4();
// compute the tangent vectors for each segment on the curve
for (var i = 0; i <= segments; i++) {
var u = i / segments;
tangents.add(getTangentAt(u, Vector3()));
tangents[i].normalize();
}
// select an initial normal vector perpendicular to the first tangent vector,
// and in the direction of the minimum tangent xyz component
normals.add(Vector3());
binormals.add(Vector3());
var min = Math.MAX_VALUE;
final tx = Math.abs(tangents[0].x).toDouble();
final ty = Math.abs(tangents[0].y).toDouble();
final tz = Math.abs(tangents[0].z).toDouble();
if (tx <= min) {
min = tx;
normal.set(1, 0, 0);
}
if (ty <= min) {
min = ty;
normal.set(0, 1, 0);
}
if (tz <= min) {
normal.set(0, 0, 1);
}
vec.crossVectors(tangents[0], normal).normalize();
normals[0].crossVectors(tangents[0], vec);
binormals[0].crossVectors(tangents[0], normals[0]);
// compute the slowly-varying normal and binormal vectors for each segment on the curve
for (var i = 1; i <= segments; i++) {
normals.add(normals[i - 1].clone());
binormals.add(binormals[i - 1].clone());
vec.crossVectors(tangents[i - 1], tangents[i]);
if (vec.length() > Math.EPSILON) {
vec.normalize();
var theta = Math.acos(MathUtils.clamp(tangents[i - 1].dot(tangents[i]),
-1, 1)); // clamp for floating pt errors
normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
}
binormals[i].crossVectors(tangents[i], normals[i]);
}
// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
if (closed == true) {
var theta =
Math.acos(MathUtils.clamp(normals[0].dot(normals[segments]), -1, 1));
theta /= segments;
if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) >
0) {
theta = -theta;
}
for (var i = 1; i <= segments; i++) {
// twist a little...
normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
binormals[i].crossVectors(tangents[i], normals[i]);
}
}
return {"tangents": tangents, "normals": normals, "binormals": binormals};
}