关于javascript:如何在Three.js中弯曲圆柱体?

How to bend a cylinder in three.js?

如何在three.js中弧形或弯曲具有变形的圆柱体几何形状?

Id要指定以下参数:

  • 弯曲开始-弯曲在圆柱高度的百分之几处开始
  • 弯头-弯头在圆柱体高度的百分之几处结束
  • angular-弯曲的强度

    parameters

我将使用滑块控制它们。我的圆柱形状是由用户绘制的贝塞尔曲线的拉伸创建的(在three.js中扩展了几何类)。

我还希望能够在彼此之上叠加多个弯曲效果。因此,弯曲可能会影响第一部分,然后第二弯曲可能会使圆柱体向后弯曲。

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


您需要做的是将您的网格物体切成薄片,并按照与我在此处的圆形相同的方式转换每个薄片:

  • 平滑地连接圆心

这样做是这样的:

  • 直角坐标系

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

    P0X0Y0Z0

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

    因此任何点P都将转换为:

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

    因此简单地基于用作参数的P.z'(弯曲形状上的弧长)计算弯曲弧的angular,如果弯曲在X附近,则将X0,Y0,Z0旋转为X1,Y1,Z1,然后将X1 = X0并且您只需要旋转其他两个向量。

    P1X1Y1Z1

  • 将P \\'转换为弯曲形式P \\'\\'

    只需执行以下操作:

    1
    P'' = P1 + P.x'*X1 + P.y'*Y1

    现在P''是形状的最终顶点。因此,您可以在转换其所有点后渲染网格。如您所见,我们不需要P.z ...,因为它已经在P1位置进行了编码。因此,也无需真正计算Z1基向量。

  • [注释]

    请注意,如果弯曲得太大,弯曲得太大会破坏网格拓扑,然后彼此之间会自动相交。

    所有相应的基向量也应具有相同的大小理想单位。

    Y0 -> Y1的旋转是简单的2D问题,如果Y0=(0,1,0)更简单,只需将其指向圆Y1=(cos(a),sin(a),0) ... ...因此您甚至不需要2D旋转公式。

    [Edit1] C / GL示例

    我很好奇,所以我拿了一根用窦螺钉固定的管子并将其弯曲...这就是结果:

    preview

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

    网格和弯曲zavit.h:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    //---------------------------------------------------------------------------
    //--- tube with sinus screw -------------------------------------------------
    //---------------------------------------------------------------------------
    const int ca=20;
    const int cb=50;
    const float r0=0.3;
    const float r1=0.35;
    const float l1=2.0;
    const float nz=5.0;
    vec3 pnt0[ca][cb];  // straight mesh
    vec3 nor0[ca][cb];
    vec2 txr0[ca][cb];
    //---------------------------------------------------------------------------
    vec3 pnt1[ca][cb];  // bended mesh
    vec3 nor1[ca][cb];
    vec2 txr1[ca][cb];
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    void obj0_init()    // sin screw
        {
        int     i,j,i0,j0;
        float   a,b,l,da,db,dl,r,s,c,tx,ty;
        float   dtx=1.0/float(ca-1),dty=1.0/float(cb-1);
        vec3    u,v;
        // pnt,txr
        da=2.0*M_PI/float(ca-1);
        db=nz*2.0*M_PI/float(cb);
        dl=l1/float(cb);
        for (a=0.0,tx=0.0,i=0;i<ca;i++,a+=da,tx+=dtx)
            {
            s=sin(a);
            c=cos(a);
            for (l=-0.5*l1,b=0,ty=0.0,j=0;j<cb;j++,b+=db,l+=dl,ty+=dty)
                {
                r=r0+((r1-r0)*cos(a+b));
                pnt0[i][j].x=r*c;
                pnt0[i][j].y=r*s;
                pnt0[i][j].z=l;
                txr0[i][j].x=tx;
                txr0[i][j].y=ty;
                }
            }
        // nor
        for (i0=ca-2,i=0;i<ca;i0=i,i++)
         for (j0=cb-1,j=0;j<cb;j0=j,j++)
            {
            u=pnt0[i][j]-pnt0[i0][j];
            v=pnt0[i][j]-pnt0[i][j0];
            nor0[i][j]=normalize(cross(v,u));
            }
        }
    //---------------------------------------------------------------------------
    void obj1_bend(vec3 center) // bend obj0 -> obj1 ... pc center, P0,X0,Y0,Z0 = unit matrix
        {
        int i,j,i0,j0;
        float a,r;
        vec3 p,p1,x1,y1,u,v;
        // bend pnt, copy txr
        r=length(center);
        for (i=0;i<ca;i++)
         for (j=0;j<cb;j++)
            {
            p=pnt0[i][j];               // p' = p

            a=p.z/r;                    // arc length -> angle [rad]
            p1=center;                  // p1 point on circleYZ (bending around X)
            p1.y-=r*cos(a);
            p1.z-=r*sin(a);
            x1=vec3(1.0,0.0,0.0);       // basis vectors
            y1=vec3(0.0,cos(a),sin(a));

            p=p1+(p.x*x1)+(p.y*y1);     // p''

            pnt1[i][j]=p;
            txr1[i][j]=txr0[i][j];
            }
        // nor
        for (i0=ca-2,i=0;i<ca;i0=i,i++)
         for (j0=cb-1,j=0;j<cb;j0=j,j++)
            {
            u=pnt1[i][j]-pnt1[i0][j];
            v=pnt1[i][j]-pnt1[i][j0];
            nor1[i][j]=normalize(cross(v,u));
            }
        }
    //---------------------------------------------------------------------------
    void obj0_draw()
        {
        int i,j;
        glColor3f(1.0,1.0,1.0);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CCW);
        for (i=0;i<ca-1;i++)
            {
            glBegin(GL_QUAD_STRIP);
            for (j=0;j<cb;j++)
                {
                glTexCoord2fv(txr0[i+1][j].dat);
                glNormal3fv  (nor0[i+1][j].dat);
                glVertex3fv  (pnt0[i+1][j].dat);
                glTexCoord2fv(txr0[i  ][j].dat);
                glNormal3fv  (nor0[i  ][j].dat);
                glVertex3fv  (pnt0[i  ][j].dat);
                }
            glEnd();
            }
        }
    //---------------------------------------------------------------------------
    void obj1_draw()
        {
        int i,j;
        glColor3f(1.0,1.0,1.0);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CCW);
        for (i=0;i<ca-1;i++)
            {
            glBegin(GL_QUAD_STRIP);
            for (j=0;j<cb;j++)
                {
                glTexCoord2fv(txr1[i+1][j].dat);
                glNormal3fv  (nor1[i+1][j].dat);
                glVertex3fv  (pnt1[i+1][j].dat);
                glTexCoord2fv(txr1[i  ][j].dat);
                glNormal3fv  (nor1[i  ][j].dat);
                glVertex3fv  (pnt1[i  ][j].dat);
                }
            glEnd();
            }
        }
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------

    以及主要的VCL应用程序代码(忽略VCL内容,只是移植/使用您需要的内容):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <math.h>
    #pragma hdrstop
    #include"Unit1.h"
    #include"gl_simple.h"
    double divide(double a,double b){ if (fabs(b)<1e-10) return 0.0; return a/b; }
    #include"GLSL_math.h"
    #include"zavit.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource"*.dfm"
    TForm1 *Form1;
    vec3 center=vec3(0.0,1.7,0.0);
    //---------------------------------------------------------------------------
    void gl_draw()
        {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        float aspect=float(xs)/float(ys);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60.0/aspect,aspect,0.1,100.0);
        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0,0.0,-5.5);
        glRotatef(80.0,1.0,0.0,0.0);        // Z+ up slightly forw
        static float ang=0.0; ang+=5.0;
        glRotatef(45.0+ang,0.0,0.0,1.0);    // X+ right forw, Y+ left forw, + animation rotation around up

        glEnable(GL_DEPTH_TEST);
        glDisable(GL_TEXTURE_2D);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

        // original mesh
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glTranslatef(-0.7,0.0,0.0);
        glColor3f(1.0,1.0,1.0);
        obj0_draw();
        glPopMatrix();

        // bended mesh
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glTranslatef(+0.7,0.0,0.0);
        glColor3f(1.0,1.0,1.0);
        obj1_draw();


        glDisable(GL_LIGHTING);
        glColor3f(1.0,0.0,0.0);
        glPointSize(10.0);
        glBegin(GL_POINTS);
        glVertex3fv(center.dat);    // bending center
        glVertex3f(0.0,0.0,0.0);    // P0
        glEnd();
        glPointSize(1.0);
        glBegin(GL_LINES);
        glVertex3fv(center.dat);
        glVertex3f(0.0,0.0,0.0);
        glEnd();

    /*
        glBegin(GL_LINES);
        glColor3f(1.0,0.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(1.0,0.0,0.0);
        glColor3f(0.0,1.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,1.0,0.0);
        glColor3f(0.0,0.0,1.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,1.0);
        glEnd();
    */

        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();

        glFlush();
        SwapBuffers(hdc);
        }
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
        {
        gl_init(Handle);
        obj0_init();
        obj1_bend(center);
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormDestroy(TObject *Sender)
        {
        gl_exit();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
        {
        gl_draw();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
        {
        gl_draw();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormResize(TObject *Sender)
        {
        gl_resize(ClientWidth,ClientHeight);
        gl_draw();
        }
    //---------------------------------------------------------------------------

    对于OpenGL,我使用的是GLEW和我的gl_simple.h,可在此处找到:

    • 完整的GL GLSL VAO / VBO C示例

    GLSL_math.h是模仿GLSL数学的我的向量数学,但是您可以使用任何向量数学...您只需要+,-,dot,cross,normalize,length,它们都是基本操作,您也可以自己编码或使用GLM或其他任何方法。 ..

    [Edit2]更多简化和可重复性

    根据您的草图和最新评论进行调整,它将不能正常运行。而是使用弧长(直线网格中的高度)作为参数。经过更多的教I之后,我得出以下结论:

    new

    为简化起见,我为每个切片添加了一个中心点,主轴方向和切片长度。这样可以简化计算...在此预览两次45度弯曲(45和-45):

    double

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    //---------------------------------------------------------------------------
    //--- tube with sinus screw -------------------------------------------------
    //---------------------------------------------------------------------------
    // https://stackoverflow.com/a/54050883/2521214
    //---------------------------------------------------------------------------
    const int   ca= 20;     // points per slice
    const int   cb=100;     // slices
    const float r0=  0.3;   // minor screw radius
    const float r1=  0.35;  // major screw radius
    const float l1=  4.0;   // tube length
    const float nz= 10.0;   // screws
    //---------------------------------------------------------------------------
    vec3 bend_pc; int bend_j0,bend_j1;  // just for debug draw
    //---------------------------------------------------------------------------
    // straight mesh
    vec3 pnt0[ca][cb];  // vertex
    vec3 nor0[ca][cb];  // normal
    vec2 txr0[ca][cb];  // texcoord
    vec3 mid0[cb];      // slice center
    vec3 dir0[cb];      // slice central axis (normalized)
    float len0[cb];     // slice arclength position
    //---------------------------------------------------------------------------
    // bended mesh
    vec3 pnt1[ca][cb];  // vertex
    vec3 nor1[ca][cb];  // normal
    vec2 txr1[ca][cb];  // texcoord
    vec3 mid1[cb];      // slice center
    vec3 dir1[cb];      // slice central axis (normalized)
    float len1[cb];     // slice arclength position
    //---------------------------------------------------------------------------
    void obj0_init()    // sin screw
        {
        int     i,j,i0,j0;
        float   a,b,l,da,db,dl,r,s,c,tx,ty;
        float   dtx=1.0/float(ca-1),dty=1.0/float(cb-1);
        vec3    u,v;
        // pnt,txr
        da=2.0*M_PI/float(ca-1);
        db=nz*2.0*M_PI/float(cb);
        dl=l1/float(cb);
        for (a=0.0,tx=0.0,i=0;i<ca;i++,a+=da,tx+=dtx)
            {
            s=sin(a);
            c=cos(a);
            for (l=-0.5*l1,b=0,ty=0.0,j=0;j<cb;j++,b+=db,l+=dl,ty+=dty)
                {
                r=r0+((r1-r0)*cos(a+b));
                pnt0[i][j].x=r*c;
                pnt0[i][j].y=r*s;
                pnt0[i][j].z=l;
                txr0[i][j].x=tx;
                txr0[i][j].y=ty;
                }
            }
        // mid,dir
        for (l=0.0,j=0;j<cb;j++,l+=dl)
            {
            mid0[j]=vec3(0.0,0.0, l-(0.5*l1));
            dir0[j]=vec3(0.0,0.0,dl);
            len0[j]=l;
            }
        // nor
        for (i0=ca-2,i=0;i<ca;i0=i,i++)
         for (j0=cb-1,j=0;j<cb;j0=j,j++)
            {
            u=pnt0[i][j]-pnt0[i0][j];
            v=pnt0[i][j]-pnt0[i][j0];
            nor0[i][j]=normalize(cross(u,v));
            }
        }
    //---------------------------------------------------------------------------
    void obj1_copy()    // obj1 = obj0
        {
        int i,j;
        for (i=0;i<ca;i++)
         for (j=0;j<cb;j++)
            {
            pnt1[i][j]=pnt0[i][j];
            txr1[i][j]=txr0[i][j];
            nor1[i][j]=nor0[i][j];
            }
        for (j=0;j<cb;j++)
            {
            mid1[j]=mid0[j];
            dir1[j]=dir0[j];
            len1[j]=len0[j];
            }
        }
    //---------------------------------------------------------------------------
    vec3 rotatex(vec3 p,vec3 p0,float a)
        {
        vec3 q; p-=p0;
        q.z=+(p.z*cos(a))+(p.y*sin(a));
        q.y=-(p.z*sin(a))+(p.y*cos(a));
        q.x=p.x;
        return q+p0;
        }
    //---------------------------------------------------------------------------
    vec3 rotatey(vec3 p,vec3 p0,float a)
        {
        vec3 q; p-=p0;
        q.x=+(p.x*cos(a))+(p.z*sin(a));
        q.z=-(p.x*sin(a))+(p.z*cos(a));
        q.y=p.y;
        return q+p0;
        }
    //---------------------------------------------------------------------------
    vec3 rotatez(vec3 p,vec3 p0,float a)
        {
        vec3 q; p-=p0;
        q.x=+(p.x*cos(a))+(p.y*sin(a));
        q.y=-(p.x*sin(a))+(p.y*cos(a));
        q.z=p.z;
        return q+p0;
        }
    //---------------------------------------------------------------------------
    void obj1_bendx(float l0,float l1,float ang)    // [units],[units],[rad] bend obj1 around x axis
        {
        int i,j,i0,j0,j1;
        float a,r,l;
        vec3 PC,p,u,v;
        vec3 P0,X0,Y0,Z0;
        // find start and end of bend
        for (j0= 0;(j0<cb)&&(len1[j0]<l0);j0++);
        for (j1=j0;(j1<cb)&&(len1[j1]<l1);j1++);
        if (j0>cb) return;          // no bend
        // coordinate system0
        P0=mid1[j0];
        Z0=normalize(dir1[j0]);
        X0=vec3(1.0,0.0,0.0);
        Y0=cross(Z0,X0);
        X0=cross(Y0,Z0);
        // bend center
        r=(l1-l0)/ang;
        PC=P0-(Y0*r);
        r=fabs(r);
        // just for debug draw
        bend_pc=PC;
        bend_j0=j0;
        bend_j1=j1;
        // bend <l0,l1)
        for (j=j0;j<cb;j++)
            {
            // arc length -> angle [rad] and length correction
            if (j<j1)
                {
                a=ang*(len1[j]-l0)/(l1-l0);
                p=Z0*(len1[j]-l0);
                }
            else{
                a=ang;
                p=Z0*(l1-l0);
                }
            // transform system0 -> system1
            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);
            }
        // nor
        for (i0=ca-2,i=0;i<ca;i0=i,i++)
         for (j0=cb-1,j=0;j<cb;j0=j,j++)
            {
            u=pnt1[i][j]-pnt1[i0][j];
            v=pnt1[i][j]-pnt1[i][j0];
            nor1[i][j]=normalize(cross(u,v));
            }
        }
    //---------------------------------------------------------------------------
    void obj0_draw()
        {
        int i,j;
        glColor3f(1.0,1.0,1.0);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CW);
        for (i=0;i<ca-1;i++)
            {
            glBegin(GL_QUAD_STRIP);
            for (j=0;j<cb;j++)
                {
                glTexCoord2fv(txr0[i+1][j].dat);
                glNormal3fv  (nor0[i+1][j].dat);
                glVertex3fv  (pnt0[i+1][j].dat);
                glTexCoord2fv(txr0[i  ][j].dat);
                glNormal3fv  (nor0[i  ][j].dat);
                glVertex3fv  (pnt0[i  ][j].dat);
                }
            glEnd();
            }
        }
    //---------------------------------------------------------------------------
    void obj1_draw()
        {
        int i,j;
        glColor3f(1.0,1.0,1.0);
        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CW);
        for (i=0;i<ca-1;i++)
            {
            glBegin(GL_QUAD_STRIP);
            for (j=0;j<cb;j++)
                {
                glTexCoord2fv(txr1[i+1][j].dat);
                glNormal3fv  (nor1[i+1][j].dat);
                glVertex3fv  (pnt1[i+1][j].dat);
                glTexCoord2fv(txr1[i  ][j].dat);
                glNormal3fv  (nor1[i  ][j].dat);
                glVertex3fv  (pnt1[i  ][j].dat);
                }
            glEnd();
            }
        }
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------

    以及VCL窗口代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <math.h>
    #pragma hdrstop
    #include"Unit1.h"
    #include"gl_simple.h"
    double divide(double a,double b){ if (fabs(b)<1e-10) return 0.0; return a/b; }
    #include"GLSL_math.h"
    #include"zavit.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource"*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    void gl_draw()
        {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        float aspect=float(xs)/float(ys);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60.0/aspect,aspect,0.1,100.0);
        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0,0.0,-5.5);
        glRotatef(-80.0,1.0,0.0,0.0);       // Z+ up slightly forw
        static float ang=0.0; ang+=5.0;
        glRotatef(45.0+ang,0.0,0.0,1.0);    // X+ right forw, Y+ left forw, + animation rotation around up

        glEnable(GL_DEPTH_TEST);
        glDisable(GL_TEXTURE_2D);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

        // [original mesh]
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glTranslatef(-0.7,0.0,0.0);
        glColor3f(1.0,1.0,1.0);
        obj0_draw();
        glPopMatrix();

        // [bended mesh]
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glTranslatef(+0.7,0.0,0.0);
        glColor3f(1.0,1.0,1.0);
        obj1_draw();

        // debug draws
        int j;
        glDisable(GL_LIGHTING);
        glDisable(GL_DEPTH_TEST);

        // global coordinates
        glBegin(GL_LINES);
        glColor3f(1.0,0.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(1.0,0.0,0.0);
        glColor3f(0.0,1.0,0.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,1.0,0.0);
        glColor3f(0.0,0.0,1.0); glVertex3f(0.0,0.0,0.0); glVertex3f(0.0,0.0,1.0);
        glEnd();

        // mesh axis
        glLineWidth(2.0); glColor3f(0.9,0.6,0.1); glBegin(GL_LINE_STRIP);
        for (j=0;j<bend_j0;j++) glVertex3fv(mid1[j].dat); if (j<cb){ glVertex3fv(mid1[j].dat); glVertex3fv(bend_pc.dat); }
        for (   ;j<bend_j1;j++) glVertex3fv(mid1[j].dat); if (j<cb){ glVertex3fv(mid1[j].dat); glVertex3fv(bend_pc.dat); }
        for (   ;j<cb     ;j++) glVertex3fv(mid1[j].dat);
        glEnd(); glLineWidth(1.0);
        // bending center
        glColor3f(1.0,0.0,0.0);
        glPointSize(10.0);
        glBegin(GL_POINTS);
        glVertex3fv(bend_pc.dat);
        glEnd();
        glPointSize(1.0);

        glEnable(GL_DEPTH_TEST);
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();

        glFlush();
        SwapBuffers(hdc);
        }
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
        {
        gl_init(Handle);
        obj0_init();
        obj1_copy();
        obj1_bendx(1.0,1.5,+45.0*M_PI/180.0);
        obj1_bendx(2.5,3.0,-45.0*M_PI/180.0);
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormDestroy(TObject *Sender)
        {
        gl_exit();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
        {
        gl_draw();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
        {
        gl_draw();
        }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormResize(TObject *Sender)
        {
        gl_resize(ClientWidth,ClientHeight);
        gl_draw();
        }
    //---------------------------------------------------------------------------

    架构是一样的,只是用法有所改变,现在将折弯直接应用到mesh1上,因此不再使用mesh0。因此,您需要在使用之前将mesh0复制到mesh1。

    我还利用了这样一个事实,即我的网格是按弧长(pnt1[angle][arclength])排序的,因此我可以处理切片而不是原始点。

    您可以类推地编写bendybendz函数,只需对数学进行一些更改以匹配交换的轴即可...如果不需要原始网格,则可以立即将其删除...

    [Edit3]与您的代码的视觉比较

    对我来说是外语,但与C / C类似,所以从快速的angular来看:

  • 使用固定的P0X0Y0Z0可以防止多次弯曲。
  • 第155行

    1
    var PC = new THREE.Vector3().copy(P0).sub(PC_X);

    它不对应我的

    1
    PC=P0-(Y0*r);

    您有不同的轴并且没有半径比例!!!如果您的轴具有不同的含义,然后再挖掘,则您只需相应地交换X,Y,Z,但仍需要使用半径。该位置是弯曲中心,如果弯曲计算错误,弯曲位置也将是错误的。...使用的轴必须不是围绕其旋转的轴,而不是圆柱体的高度。

  • 第173行

    1
    2
    var p = new THREE.Vector3().copy(X0);
    p.multiplyScalar(slice_arc_length[j]-l0);

    我知道了:

    1
    p=Z0*(len1[j]-l0);

    因此再次明显不同的轴。您应该使用圆柱轴的高度...在180行的else中也是如此。

  • 所以,如果我看对的话,这是轴对应关系

    1
    2
    3
    4
    mine    yours   meaning
    X0      Z0      bending rotation axis
    Y0      X0
    Z0      Y0      cylinder height
  • 第182行

    您得到了:

    1
    2
    3
    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); }

    我知道了:

    1
    2
    3
    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);

    如果mid[]为零,则仍然需要使用-p。同样,您正在绕y旋转,但是从先前代码中使用的轴对应关系出发,您应该绕z旋转!!!

  • 因此,您错误地设置了旋转中心,绕了错误的轴旋转。还要检查是否正确选择了轴(它们在网格中需要具有相同的含义)。

    [Edit4]另一个比较

  • 第105行

    1
    2
    3
    var Z_Copy = new THREE.Vector3().copy(Z0);
    Z_Copy.multiplyScalar(r);
    var PC = new THREE.Vector3().copy(P0).sub(Z_Copy);

    应为:

    1
    2
    3
    var X_Copy = new THREE.Vector3().copy(X0);
    X_Copy.multiplyScalar(r);
    var PC = new THREE.Vector3().copy(P0).sub(X_Copy);

    当您围绕z旋转时,因此必须将中心PC沿其他轴移动...因此X这就是为什么弯曲仅移动而不是旋转的原因。

  • 看起来其余的代码应该没问题,但是要确保我还会渲染middir数组,以查看它们是否真的相对于网格应位于(网格的黄色中心线)预览中的网格)。折弯工作后,还应该从mid,dir移植P0X0Y0Z0计算,以便可以重复应用折弯...

    如果我换到你的轴上,那就是:

    1
    2
    3
    4
    5
    P0=mid1[j0];
    Y0=normalize(dir1[j0]);
    Z0=vec3(0.0,0.0,1.0);
    X0=cross(Y0,Z0);
    Y0=cross(Z0,X0);

    [edit5]另一个比较

    您一次又一次地犯了同样的错误……错误地重写了方程式,所以没有人动脑筋了。这次:

  • 第186行:

    1
    var point_temp = new THREE.Vector3().copy(slices[j][i]);

    您忘记添加point_temp.sub(p);,这是形状变形的原因,并且很可能也是不同旋转方式的原因。

  • 您的rotatez

    您输入的是错误的:

    1
    2
    3
    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;

    我得到了

    1
    2
    3
    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;

    但无论如何也可能是:

    1
    2
    3
    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;

    尝试哪种方法能使我对rotatex的方程式进行测试而不是针对rotatez ...这两个版本只是沿相反的方向旋转,因此两者都是正确的,但是代码只能使用一个正确地工作。

  • angular单位

    中线的弯曲(在代码中您获得了"正确"的弯曲)与围绕PC的旋转不同,它可能是由#2引起的,但也可能是由错误的angular单位引起的。您的cossin函数是否需要[deg][rad]?当前所有计算的angular都在[rad]