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

时间:2019-01-03 20:32:14

标签: javascript three.js geometry trigonometry

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

Id要指定以下参数:

  • 弯曲开始-弯曲开始于圆柱高度的百分比
  • 弯曲结束-弯曲结束于圆柱高度的百分比
  • 角度-弯曲的强度

    parameters

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

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

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

1 个答案:

答案 0 :(得分:2)

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

就是这样完成的:

  1. 直线坐标系

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

    P0X0Y0Z0

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

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

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

    如此简单地根据用作参数的P.z'(弯曲形状上的弧长)计算弯曲弧的角度,然后将X0,Y0,Z0旋转到X1,Y1,Z1(如果弯曲围绕{ {1}},然后X,您只需要旋转其他两个向量。

    P1X1Y1Z1

  4. 将P'转换为弯曲形式P''

    只需执行以下操作:

    X1 = X0

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

[注释]

请注意,弯曲太大会破坏网格拓扑。如果弯曲太多,则可以使切片彼此相交。

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

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

[Edit1] C ++ / GL示例

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

preview

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

网格和弯曲 zavit.h

P0,X0,Y0,Z0

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

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

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

GLSL_math.h 是我的矢量数学,模仿了 GLSL 数学,但是您可以使用任何矢量数学...您只需要//--------------------------------------------------------------------------- #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(); } //--------------------------------------------------------------------------- ,它们都是基本的操作,您也可以自己编写代码,也可以使用 GLM 或其他任何方法

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

根据您的草图和后期注释,这将无法正常运行。而是使用弧长(直线网格中的高度)作为参数。经过更多的教I之后,我得出以下结论:

new approach

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

double bend

RGB线是弯曲的网格渲染的全局坐标系,淡黄色是网格中心轴+用于调试的最后一个弯曲的弯曲范围,红色是最后一个弯曲中心。

此处为新的C ++代码+,-,dot,cross,normalize,length

zavit.h

以及VCL窗口代码:

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

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

我还利用了这样一个事实,即我的网格是按弧长(//--------------------------------------------------------------------------- #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(); } //--------------------------------------------------------------------------- )排序的,因此我可以处理切片而不是原始点。

您可以类推地编写pnt1[angle][arclength]bendy函数,只需对数学进行一些更改即可匹配交换的轴...如果您不需要原始网格,则可以立即将其删除... < / p>

[Edit3]与您的code的视觉比较

它对我来说是外语,但类似于C / C ++,所以从快速的角度来看:

  1. 您使用固定的bendz,这可以防止您多次弯曲。
  2. 第155行

    P0X0Y0Z0

    它与我的不符

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

    您有不同的轴并且没有半径比例!!!如果您的轴的含义与我的不同,则只需相应地交换PC=P0-(Y0*r); ,但仍需要使用半径。该位置是弯曲中心,因此如果错误地计算出弯曲也将是错误的位置。...使用的轴必须不是围绕其旋转的轴,而不是圆柱体的高度。

  3. 第173行

    X,Y,Z

    我知道了

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

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

  4. 所以,如果我看对了,这就是轴对应关系

    p=Z0*(len1[j]-l0);
    
  5. 182行

    您得到了:

    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); 为零,那么仍然需要使用mid[]。同样,您正在绕-p旋转,但是从先前代码中使用的轴对应关系来看,您应该绕着y旋转!!!

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

[Edit4]另一个比较

  1. 第105行

    z

    应为:

    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); 旋转,所以中心Z必须在其他轴上移动...因此PC就是弯曲而不是旋转的原因。

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

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

mid,dir

[edit5]另一个比较

您一次又一次地犯同样的错误……错误地重写了方程式,因此没有头脑的人无法正常工作。这次:

  1. 在第186行:

    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]); ,这是形状变形的原因,而且很可能也是由于旋转不同所致。

  2. 您的point_temp.sub(p);

    您得到的是错误的:

    rotatez

    我知道了

    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; 的公式进行测试,而不对rotatex进行测试...这两个版本只是朝相反的方向旋转,因此两者都是正确的,但是代码只能对其中一个起作用。

  3. 角度单位

    中线的弯曲(即您在代码中“正确”的弯曲)与围绕rotatez的旋转不同,这可能是由#2 引起的,但也可能是由于错误的角度单位。您的PCcos函数是否需要sin[deg]?当前所有计算的角度都在[rad]中。