Three.js - 如何在ExtrudeGeometry中使用frames选项

时间:2015-04-01 12:11:03

标签: three.js

我找不到关于如何在Three.js中使用ExtrudeGeometry的 frames 选项的解释。其documentation说:

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

但我不明白必须如何定义 frames 。我认为使用“frames”选项,传递三个数组用于切线,法线和副法线(以某种方式计算),但如何在中传递它们?...可能(如{{3} } for morphNormals ):

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

使用相同长度的三个数组(可能对应于ExtrudeGeometry中的 steps curveSegments 选项)?

非常感谢您的解释。

修改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);

修改2

很久以前,我打开了here主题,我使用了this解决方案:

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));
}

但我正在考虑将spline_2的第一个点(t = 0)的正切,法线和副法线设置为与spline_1的最后一个点(t = 1)相同的可能性;所以我想如果那个选项,框架,可以以某种方式返回有用的目的。可以覆盖相应列表中的切线,法线和副法线的值,以获得 spline_1 的最后一个点(t = 1)和第一个点(t = 0)的相同值) spline_2 ,以指导挤压?例如,对于 spline_2 的“t = 0”的切线:

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

也为法线[0] binormals [0] 做同样的事情,以确保的最后一点(t = 1)具有相同的方向spline_1 spline_2的第一个(t = 0)

编辑3

我正在尝试为 mypath 的每个控制点可视化切线正常 binormal “(spline)使用 ArrowHelper ,但正如您在this中看到的那样(在场景加载时,您需要慢慢缩小场景,直到看到ArrowHelpers,才能找到它们)。相对代码从小提琴中的第122行到第152行开始,ArrowHelper不是从原点开始,而是远离它。如何获得demo参考演示的相同结果(当您选中“Debug normals”复选框时)?

编辑4

Tangents, normals, binormals

我在A点(=原点)绘制了分别结束(蓝色样条)和开始(红色样条)的两个样条曲线,在每个样条曲线的A点显示相切,法线和副法线向量(使用蓝色样条标签的青色)和红色样条标签的黄色。)

如上所述,为了对齐并使两个样条连续,我想要利用三个向量(正切,正规和副正规)。理论上,我应该使用哪种数学运算来转动蓝色样条曲线的端面,使其观察红色样条曲线的初始面(黄色面),以便相应的切线(D,D' - 隐藏在图片中),法线(B,B')和副法线(C,C')是否对齐?我应该使用四元数的“.setFromUnitVectors(vFrom,VTO)”方法吗?在this我读到:&lt;&lt;将此四元数设置为将vFrom方向向量旋转到向量方向VTO ... vFrom VTO所需的旋转,并假设为标准化。 &GT;&GT;所以,我可能需要定义三个四元数:

  1. 四元数,用于在归一化切线D'向量的方向上旋转归一化切线D向量
  2. 四元数,用于在归一化法线B'向量的方向上旋转归一化法线B向量
  3. 四元数,用于在归一化的副法C'向量的方向上旋转归一化的副法C向量
  4. 使用:

    • vFrom =标准化的D,B和C向量
    • VTO =标准化的D',B'和C'向量

    分别将三个四元数分别应用于D,B和C(未标准化)?

    再次感谢

    编辑5

    我尝试了这段代码(在图片中查看如何对齐矢量)但没有任何改变:

    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
    

    也没有其他方式:

    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 );
    

0 个答案:

没有答案