Как согнуть цилиндр в three.js? - PullRequest
0 голосов
/ 03 января 2019

Как бы вы изогнули или изогнули геометрию типа цилиндра (которая имеет искажение) в three.js?

Я бы хотел указать эти параметры:

  • Bend Start - при каком проценте высоты цилиндра начинается изгиб
  • Конец изгиба - при каком проценте высоты цилиндра заканчивается изгиб
  • Угол - насколько сильный изгиб

    parameters

Я буду управлять ими с помощью ползунков.Моя форма цилиндра создается из вытянутой кривой Безье, которую рисует пользователь (расширение класса геометрии в three.js).

Я также хотел бы иметь возможность накладывать несколько эффектов изгиба поверх каждогоДругой.Таким образом, изгиб может повлиять на первую часть, затем второй изгиб может отогнуть цилиндр назад.

Я не лучший в математике, поэтому я прошу советы или формулы, которые могли бы сделать это вThree.js.Я думаю, может быть, я мог бы поставить линию на центральной оси, а затем согнуть ее с помощью кривой Безье.Оттуда я мог бы использовать положение линий, чтобы влиять на вершины цилиндра.Это звучит как хорошая идея?

1 Ответ

0 голосов
/ 05 января 2019

Что вам нужно сделать, это разрезать вашу сетку на кусочки и преобразовать каждый кусочек таким же образом, как я делаю круги здесь:

Это делается так:

  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, если изгиб составляет около Xзатем X1 = X0 и вам нужно повернуть только два других вектора.

    P1X1Y1Z1

  4. преобразовать P 'в изогнутыйform P ''

    просто сделайте это:

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

    теперь P'' - это конечная вершина вашей фигуры.Таким образом, вы можете визуализировать вашу сетку после конвертации всех ее точек.Как видите, нам не нужен P.z ..., поскольку он уже закодирован в позиции P1.Таким образом, также нет необходимости вычислять базовый вектор Z1.

[Примечания]

Остерегайтесь слишком больших изгибовможет испортить вашу топологию меша , если вы слишком сильно согнете, то вы можете самостоятельно пересекать срезы между собой.

Также все соответствующие базисные векторы должны иметь одинаковый размер. В идеальном случае это единица измерения.

Поворот Y0 -> Y1 - это простая двумерная задача, а если Y0=(0,1,0), то еще проще просто указать точку на окружности Y1=(cos(a),sin(a),0) ... так что вам даже не нужна формула двухмерного вращения.

[Edit1] Пример C ++ / GL

Мне было любопытно, поэтому я взял сгенерированную трубку с помощью синусового винта и согнул ее ... Вот результат:

preview

Я визуализировал прямые и изогнутые сетки для визуального сравнения.Красная точка - центр изгиба, и линия соединяет его с P0.Я выбрал P0,X0,Y0,Z0 для соответствия единичной матрице.Пример преобразован так, чтобы он соответствовал изображениям в этом вопросе (в неанимированном состоянии).Вот код C ++ / GL , с которым я это сделал:

Сетка и изгиб Завит.h :

//---------------------------------------------------------------------------
//--- 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 , просто портируйте / используйте то, что вам нужно):

//---------------------------------------------------------------------------
#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 , который можно найти здесь:

GLSL_math.h - это моя векторная математика, имитирующая GLSL математика, но вы можете использовать любую векторную математику ... Вам просто нужно +,-,dot,cross,normalize,length, которые являются основными операциямии вы можете написать его самостоятельно или использовать GLM или что-то еще ...

[Edit2] еще несколько упрощений и повторяемости

ХорошоСогласно вашему эскизу и поздним комментариям, он не будет работать с высотой.Вместо этого используйте длины дуги (высота в сетке прямой формы) в качестве параметров.После некоторого дополнительного обучения я получил следующее:

new approach

Для упрощения я добавил для каждого среза центральную точку, направление главной оси и длину среза.Это позволяет гораздо проще вычислений ... Здесь предварительный просмотр примененного изгиба на 45 градусов дважды (+45 и -45):

double bend

Строки RGB являются глобальнымисистема координат для визуализации согнутой сетки, желтоватый - это центральная ось сетки + диапазон изгиба последнего изгиба для отладки, а красный - последний центр изгиба.

здесь новый код C ++ zavit.h:

//---------------------------------------------------------------------------
//--- 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:

//---------------------------------------------------------------------------
#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]), поэтому я могу обрабатывать кусочки вместо необработанных точек.

Вы можете аналогичным образом написать функции bendy и bendz, просто немного изменив математику, чтобы она соответствовала измененным осям ... Если вам не нужна оригинальная сетка, вы можете удалить ее сейчас ...

[Edit3] визуальное сравнение с вашим кодом

Это иностранный язык для меня, но похож на C / C ++, так что из быстрого просмотра:

  1. вы используете фиксированный P0X0Y0Z0, который не позволяет применять изгиб более одного раза.
  2. в строке 155

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

    не соответствует моему

    PC=P0-(Y0*r);
    

    у вас другая ось и нет радиуса если ваши оси имеют другое значение, чем мое, тогда вы просто поменяете X,Y,Z соответственно, но вам все равно нужно использовать радиус. Это позиция, если центр изгиба, так что если неправильно вычислен, изгиб тоже неправильный ... Используемая ось должна быть не той, вокруг которой выполняется вращение, а не высотой цилиндра.

  3. по строке 173

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

    Я получил:

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

    так явно другая ось снова. Вы должны использовать высоту оси цилиндра ... То же самое относится и к остальному в строке 180.

  4. Так что, если я правильно понял, это соответствие оси

    mine    yours   meaning
    X0      Z0      bending rotation axis
    Y0      X0
    Z0      Y0      cylinder height
    
  5. строка 182

    Вы получили:

    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, но из соответствия оси, которое вы используете в предыдущем коде, вы должны вращаться вокруг z !!!

То есть вы неправильно устанавливаете центр вращения, вращаетесь вокруг неправильной оси. Также проверьте, правильно ли вы выбрали оси (они должны иметь одинаковое значение в вашей сетке).

[Edit4] другое сравнение

  1. строка 105

    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 должен быть смещен по другой оси ... поэтому X, поэтому ваш изгиб просто смещен, а не повернут.

Похоже, что остальная часть кода должна быть в порядке, но чтобы быть уверенным, я бы также визуализировал массивы mid и dir, чтобы увидеть, действительно ли они находятся там, где они должны быть относительно сетки (желтая центральная линия сетка в моем превью). После того, как изгиб сработает, вы также должны перенести вычисление P0X0Y0Z0 из mid,dir, чтобы вы могли применять изгиб многократно ...

Если я поменяюсь на твои оси, это будет:

P0=mid1[j0];
Y0=normalize(dir1[j0]);
Z0=vec3(0.0,0.0,1.0);
X0=cross(Y0,Z0);
Y0=cross(Z0,X0);

[edit5] другое сравнение

Вы повторяете одни и те же ошибки снова и снова ... неправильно переписываете уравнения, так что никакой мозг не работает правильно. На этот раз:

  1. В строке 186:

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

    Вы забыли добавить point_temp.sub(p);, который является причиной искажения формы и, скорее всего, также для другого поворота.

  2. ваш 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, проверенные не для rotatez ... две версии просто вращаются в противоположных направлениях, поэтому обе верны, но код может корректно работать только с одной.

  3. угловые единицы

    изгиб средней линии (той, которую вы получили «правильно» в коде) не похож на поворот вокруг PC, это может быть вызвано # 2 , но это также может быть вызвано неправильными угловыми единицами , Ваши функции cos и sin нуждаются в [deg] или [rad]? В настоящее время все рассчитанные углы приведены в [rad].

...