0

I can't find anywhere an explaination about how to use the frames option for ExtrudeGeometry in Three.js. Its documentation says:

extrudePath — THREE.CurvePath. 3d spline path to extrude shape along. (creates Frames if (frames aren't defined)

frames — THREE.TubeGeometry.FrenetFrames. containing arrays of tangents, normals, binormals

but I don't understand how frames must be defined. I think using the "frames" option, passing three arrays for tangents, normals and binormals (calculated in some way), but how to pass them in frames?... Probably (like here for morphNormals):

    frames = { tangents: [ new THREE.Vector3(), ... ], normals: [ new THREE.Vector3(), ... ], binormals: [ new THREE.Vector3(), ... ] };

with the three arrays of the same lenght (perhaps corresponding to steps or curveSegments option in ExtrudeGeometry)?

Many thanks for an explanation.

Edit 1:

String.prototype.format = function () {
    var str = this;
    for (var i = 0; i < arguments.length; i++) {
        str = str.replace('{' + i + '}', arguments[i]);
    }
    return str;
}

var numSegments = 6;
var frames = new THREE.TubeGeometry.FrenetFrames( new THREE.SplineCurve3(spline), numSegments );
var tangents = frames.tangents,
    normals = frames.normals,
    binormals = frames.binormals;

var tangents_list = [],
    normals_list = [],
    binormals_list = [];
for ( i = 0; i < numSegments; i++ ) {
    var tangent = tangents[ i ];
    var normal = normals[ i ];
    var binormal = binormals[ i ];
    tangents_list.push("({0}, {1}, {2})".format(tangent.x, tangent.y, tangent.z));
    normals_list.push("({0}, {1}, {2})".format(normal.x, normal.y, normal.z));
    binormals_list.push("({0}, {1}, {2})".format(binormal.x, binormal.y, binormal.z));
}
alert(tangents_list);
alert(normals_list);
alert(binormals_list);

Edit 2

Times ago, I opened this topic for which I used this solution:

var spline = new THREE.SplineCurve3([
    new THREE.Vector3(20.343, 19.827, 90.612),  // t=0
    new THREE.Vector3(22.768, 22.735, 90.716),  // t=1/12
    new THREE.Vector3(26.472, 23.183, 91.087),  // t=2/12
    new THREE.Vector3(27.770, 26.724, 91.458),  // t=3/12
    new THREE.Vector3(31.224, 26.976, 89.861),  // t=4/12
    new THREE.Vector3(32.317, 30.565, 89.396),  // t=5/12
    new THREE.Vector3(31.066, 33.784, 90.949),  // t=6/12
    new THREE.Vector3(30.787, 36.310, 88.136),  // t=7/12
    new THREE.Vector3(29.354, 39.154, 90.152),  // t=8/12
    new THREE.Vector3(28.414, 40.213, 93.636),  // t=9/12
    new THREE.Vector3(26.569, 43.190, 95.082),  // t=10/12
    new THREE.Vector3(24.237, 44.399, 97.808),  // t=11/12
    new THREE.Vector3(21.332, 42.137, 96.826)   // t=12/12=1
]);

var spline_1 = [], spline_2 = [], t;

for( t = 0; t <= (7/12); t+=0.0001) {
    spline_1.push(spline.getPoint(t));
}

for( t = (7/12); t <= 1; t+=0.0001) {
    spline_2.push(spline.getPoint(t));
}

But I was thinking the possibility to set the tangent, normal and binormal for the first point (t=0) of spline_2 to be the same of last point (t=1) of spline_1; so I thought if that option, frames, could return in some way useful for the purpose. Could be possible to overwrite the value for a tangent, normal and binormal in the respective list, to obtain the same value for the last point (t=1) of spline_1 and the first point (t=0) of spline_2, so to guide the extrusion? For example, for the tangent at "t=0" of spline_2:

tangents[0].x = 0.301;
tangents[0].y = 0.543;
tangents[0].z = 0.138;

doing the same also for normals[0] and binormals[0], to ensure the same orientation for the last point (t=1) of spline_1 and the first one (t=0) of spline_2

Edit 3

I'm trying to visualize the tangent, normal and binormal for each control point of "mypath" (spline) using ArrowHelper, but, as you can see in the demo (on scene loading, you need zoom out the scene slowly, until you see the ArrowHelpers, to find them. The relative code starts from line 122 to line 152 in the fiddle), the ArrowHelper does not start at origin, but away from it. How to obtain the same result of this reference demo (when you check the "Debug normals" checkbox)?

Edit 4

Tangents, normals, binormals

I plotted two splines that respectively end (blue spline) and start (red spline) at point A (= origin), displaying tangent, normal and binormal vectors at point A for each spline (using cyan color for the blue spline's labels, and yellow color for the red spline's labels).

As mentioned above, to align and make continuous the two splines, I thought to exploit the three vectors (tangent, normal and binormal). Which mathematical operation, in theory, should I use to turn the end face of blue spline in a way that it views the initial face (yellow face) of red spline, so that the respective tangents (D, D'-hidden in the picture), normals (B, B') and binormals (C, C') are aligned? Should I use the ".setFromUnitVectors (vFrom, VTO)" method of quaternion? In its documentation I read: << Sets this quaternion to the rotation required to rotate vFrom direction vector to vector direction VTO ... vFrom VTO and are assumed to be normalized. >> So, probably, I need to define three quaternions:

  1. quaternion for the rotation of the normalized tangent D vector in the direction of the normalized tangent D' vector
  2. quaternion for the rotation of the normalized normal B vector in the direction of the normalized normal B' vector
  3. quaternion for the rotation of the normalized binormal C vector in the direction of the normalized binormal C' vector

with:

  • vFrom = normalized D, B and C vectors
  • VTO ​​= normalized D', B' and C' vectors

and apply each of the three quaternions respectively to D, B and C (not normalized)?

Thanks a lot again

Edit 5

I tried this code (looking in the image how to align the vectors) but nothing has changed:

var numSegments_1 = points_1.length; // points_1 = list of points
var frames_1 = new THREE.TubeGeometry.FrenetFrames( points_1_spline, numSegments_1, false ); // path, segments, closed
var tangents_1 = frames_1.tangents,
    normals_1 = frames_1.normals,
    binormals_1 = frames_1.binormals;

var numSegments_2 = points_2.length;
var frames_2 = new THREE.TubeGeometry.FrenetFrames( points_2_spline, numSegments_2, false );
var tangents_2 = frames_2.tangents,
    normals_2 = frames_2.normals,
    binormals_2 = frames_2.binormals;

var b1_b2_angle = binormals_1[ binormals_1.length - 1 ].angleTo( binormals_2[ 0 ] ); // angle between binormals_1 (at point A of spline 1) and binormals_2 (at point A of spline 2)
var quaternion_n1_axis = new THREE.Quaternion();
quaternion_n1_axis.setFromAxisAngle( normals_1[ normals_1.length - 1 ], b1_b2_angle ); // quaternion equal to a rotation on normal_1 as axis
var vector_b1 = binormals_1[ binormals_1.length - 1 ];
vector_b1.applyQuaternion( quaternion_n1_axis ); // apply quaternion to binormals_1

var n1_n2_angle = normals_1[ normals_1.length - 1 ].angleTo( normals_2[ 0 ] ); // angle between normals_1 (at point A of spline 1) and normals_2 (at point A of spline 2)
var quaternion_b1_axis = new THREE.Quaternion();
quaternion_b1_axis.setFromAxisAngle( binormals_1[ binormals_1.length - 1 ], -n1_n2_angle ); // quaternion equal to a rotation on binormal_1 as axis
var vector_n1 = normals_1[ normals_1.length - 1 ];
vector_n1.applyQuaternion( quaternion_b1_axis ); // apply quaternion to normals_1

nothing in this other way also:

var numSegments_1 = points_1.length; // points_1 = list of points
var frames_1 = new THREE.TubeGeometry.FrenetFrames( points_1_spline, numSegments_1, false ); // path, segments, closed
var tangents_1 = frames_1.tangents,
    normals_1 = frames_1.normals,
    binormals_1 = frames_1.binormals;

var numSegments_2 = points_2.length;
var frames_2 = new THREE.TubeGeometry.FrenetFrames( points_2_spline, numSegments_2, false );
var tangents_2 = frames_2.tangents,
    normals_2 = frames_2.normals,
    binormals_2 = frames_2.binormals;

var quaternion_n1_axis = new THREE.Quaternion();
quaternion_n1_axis.setFromUnitVectors( binormals_1[ binormals_1.length - 1 ].normalize(), binormals_2[ 0 ].normalize() );
var vector_b1 = binormals_1[ binormals_1.length - 1 ];
vector_b1.applyQuaternion( quaternion_n1_axis );

var quaternion_b1_axis = new THREE.Quaternion();
quaternion_b1_axis.setFromUnitVectors( normals_1[ normals_1.length - 1 ].normalize(), normals_2[ 0 ].normalize() );
var vector_n1 = normals_1[ normals_1.length - 1 ];
vector_n1.applyQuaternion( quaternion_b1_axis );
Community
  • 1
  • 1
Riccardo Volpe
  • 1,471
  • 1
  • 16
  • 30

0 Answers0