Javascript 如何在three.js中弯曲圆柱体?

Javascript 如何在three.js中弯曲圆柱体?,javascript,three.js,geometry,trigonometry,Javascript,Three.js,Geometry,Trigonometry,在three.js中,您将如何弧形或弯曲圆柱体类型的几何体(具有变形) 我想指定这些参数: 折弯开始-折弯开始的气缸高度百分比是多少 弯曲端-弯曲端在圆柱体高度的百分之几处 角度弯曲的强度 我将用滑块控制它们。我的圆柱体形状是从用户绘制的bezier曲线的拉伸中创建的(在three.js中扩展了geometry类) 我还希望能够将几个弯曲效果层叠在一起。因此,弯曲可能会影响第一个零件,然后第二个弯曲可能会使圆柱体向后弯曲 我在数学方面不是最好的,所以这就是为什么我要求在three.js中提

在three.js中,您将如何弧形或弯曲圆柱体类型的几何体(具有变形)

我想指定这些参数:

  • 折弯开始-折弯开始的气缸高度百分比是多少
  • 弯曲端-弯曲端在圆柱体高度的百分之几处
  • 角度弯曲的强度

我将用滑块控制它们。我的圆柱体形状是从用户绘制的bezier曲线的拉伸中创建的(在three.js中扩展了geometry类)

我还希望能够将几个弯曲效果层叠在一起。因此,弯曲可能会影响第一个零件,然后第二个弯曲可能会使圆柱体向后弯曲


我在数学方面不是最好的,所以这就是为什么我要求在three.js中提供可以做到这一点的提示或公式。我在想也许我可以在中心轴上画一条线,然后用贝塞尔曲线弯曲它。从那里我可以使用线的位置来影响圆柱体的顶点。这听起来是个好主意吗?

您需要做的是将网格切割成片,并以与我在这里做圆相同的方式转换每个片:

就是这样做的:

  • 直形坐标系

    创建位置
    P0
    和3个基向量
    X0、Y0、Z0
    ,以直线形式表示网格坐标。假设
    Z0
    是要弯曲的轴

  • 将每个顶点转换为
    P0、X0、Y0、Z0
    局部坐标

    因此,任何点
    p
    都被转换为:

    P.x' = dot( P-P0 , X0 )
    P.y' = dot( P-P0 , Y0 )
    P.z' = dot( P-P0 , Z0 )
    
  • 创建折弯形状坐标系
    P1、X1、Y1、Z1

    因此,只需根据用作参数(弯曲形状上的弧长)的
    p.z'
    计算弯曲弧的角度,并将
    X0,Y0,Z0
    旋转到
    X1,Y1,Z1
    中,如果弯曲在
    X
    附近,则
    X1=X0
    并且只需旋转其他两个矢量

  • 将p'转换为弯曲形式p'

    只需这样做:

    P'' = P1 + P.x'*X1 + P.y'*Y1
    
    现在,
    p'
    是形状的最终顶点。因此,可以在转换网格的所有点后渲染网格。如您所见,我们不需要
    P.z
    。。。由于其已编码在
    P1
    位置。因此也不需要计算
    Z1
    基向量

  • [Notes]

    请注意,过大的弯曲可能会损坏网格拓扑如果弯曲过多,则可以使切片彼此自相交

    此外,所有相应的基向量应具有相同的单位大小

    Y0->Y1
    的旋转是一个简单的二维问题,如果
    Y0=(0,1,0)
    它甚至更简单,只需在圆上点
    Y1=(cos(a),sin(a),0)
    。。。因此,您甚至不需要二维旋转公式

    [Edit1]C++/GL示例

    mine    yours   meaning
    X0      Z0      bending rotation axis
    Y0      X0
    Z0      Y0      cylinder height
    
    我很好奇,所以我拿了一个有窦状螺钉的试管,把它弯曲。。。结果是:

    我渲染了直网格和弯曲网格以进行视觉比较。红色点是折弯中心,该线将其连接到
    P0
    。我选择了
    P0,X0,Y0,Z0来匹配单位矩阵。该示例经过转换,以便与此问题中的图像匹配(处于未设置动画的状态)。这里是我使用的C++/GL代码:

    网格和弯曲zavit.h

    //---------------------------------------------------------------------------
    //---窦形螺钉管-------------------------------------------------
    //---------------------------------------------------------------------------
    常数int ca=20;
    常数int cb=50;
    常数浮点r0=0.3;
    常数浮点r1=0.35;
    常量浮点l1=2.0;
    常数浮动nz=5.0;
    vec3-pnt0[ca][cb];//直网
    vec3-nor0[ca][cb];
    vec2-txr0[ca][cb];
    //---------------------------------------------------------------------------
    vec3-pnt1[ca][cb];//弯网
    vec3-nor1[ca][cb];
    vec2-txr1[ca][cb];
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    void obj0_init()//单螺钉
    {
    inti,j,i0,j0;
    浮点数a、b、l、da、db、dl、r、s、c、tx、ty;
    浮子dtx=1.0/浮子(ca-1),dty=1.0/浮子(cb-1);
    vec3u,v;
    //pnt,txr
    da=2.0*M_PI/浮点数(ca-1);
    db=nz*2.0*M_π/浮点数(cb);
    dl=l1/浮点数(cb);
    
    对于(a=0.0,tx=0.0,i=0;我看了一下。如果你想看更多的东西,我想那篇文章不会有帮助,因为我的形状是扭曲的。你知道如何弯曲扭曲的几何体吗?@Spektre这是一个代码笔,它的形状与我试图弯曲的形状相似。但不是平滑的圆弧,而是试图控制它nd more@TintinabulatorZea
    P0
    是整个网格的单点,是的,它也可以是几何体的中心…,
    P1
    是每个切片(P.z'坐标),如果你的
    X0,Y0,Z0
    向量匹配X,Y,Z坐标轴,那么你不需要点积,只需使用
    P'=P-P0
    。在我的点积中
    X0
    是全向量,所以
    P.X'=dot(P-P0,X0)=(P.X-P0.X)*X0.X+(P.Y-P0.Y)*X0.Y+(P.Z-P0.Z)*X0.z
    @TintinabulatorZea是的,你是对的,P.z'为零的切片没有弯曲…z轴上距离
    P0
    越远,角度和弯曲度越大…顺便说一句,如果你熟悉4x4变换矩阵,3x点积是单矩阵乘以向量…参见…Z0的旋转公式也是2D或者只是用y和z坐标指向与Y0->Y1相同的圆,
    (sin(a),0,cos(a))
    我想……或者
    (cos(a),0,sin(a))
    +/-如果needed@TintinabulatorZea我广告
    PC=P0-(Y0*r);
    
    var p = new THREE.Vector3().copy(X0);
    p.multiplyScalar(slice_arc_length[j]-l0);
    
    p=Z0*(len1[j]-l0);
    
    mine    yours   meaning
    X0      Z0      bending rotation axis
    Y0      X0
    Z0      Y0      cylinder height
    
    center_points[j] = rotatey(p,PC,a);
    center_vector[j] = rotatey(center_vector[j], new THREE.Vector3(0,0,0),a);
    for (var i=0; i<20; i++){ slices[i][j]= rotatey(slices[i][j].sub(p),PC,a); }
    
    mid1[j]=rotatex(mid1[j]-p,PC,a);
    dir1[j]=rotatex(dir1[j],vec3(0.0,0.0,0.0),a);
    for (i=0;i<ca;i++) pnt1[i][j]=rotatex(pnt1[i][j]-p,PC,a);
    
    var Z_Copy = new THREE.Vector3().copy(Z0);
    Z_Copy.multiplyScalar(r);
    var PC = new THREE.Vector3().copy(P0).sub(Z_Copy);
    
    var X_Copy = new THREE.Vector3().copy(X0);
    X_Copy.multiplyScalar(r);
    var PC = new THREE.Vector3().copy(P0).sub(X_Copy);
    
    P0=mid1[j0];
    Y0=normalize(dir1[j0]);
    Z0=vec3(0.0,0.0,1.0);
    X0=cross(Y0,Z0);
    Y0=cross(Z0,X0);
    
    var point_temp = new THREE.Vector3().copy(slices[j][i]);
    
    p.x=+(p.x*Math.cos(a))+(p.y*Math.sin(a));
    p.y=+(p.x*Math.sin(a))+(p.y*Math.cos(a));
    p.z=p.z;
    
    p.x=+(p.x*Math.cos(a))+(p.y*Math.sin(a));
    p.y=-(p.x*Math.sin(a))+(p.y*Math.cos(a));
    p.z=p.z;
    
    p.x=+(p.x*Math.cos(a))-(p.y*Math.sin(a));
    p.y=+(p.x*Math.sin(a))+(p.y*Math.cos(a));
    p.z=p.z;