Что вам нужно сделать, это разрезать вашу сетку на кусочки и преобразовать каждый кусочек таким же образом, как я делаю круги здесь:
Это делается так:
система координат прямой формы
Создание позиции 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 'в изогнутый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
Мне было любопытно, поэтому я взял сгенерированную трубку с помощью синусового винта и согнул ее ... Вот результат:
Я визуализировал прямые и изогнутые сетки для визуального сравнения.Красная точка - центр изгиба, и линия соединяет его с 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] еще несколько упрощений и повторяемости
ХорошоСогласно вашему эскизу и поздним комментариям, он не будет работать с высотой.Вместо этого используйте длины дуги (высота в сетке прямой формы) в качестве параметров.После некоторого дополнительного обучения я получил следующее:
Для упрощения я добавил для каждого среза центральную точку, направление главной оси и длину среза.Это позволяет гораздо проще вычислений ... Здесь предварительный просмотр примененного изгиба на 45 градусов дважды (+45 и -45):
Строки 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 ++, так что из быстрого просмотра:
- вы используете фиксированный
P0X0Y0Z0
, который не позволяет применять изгиб более одного раза.
в строке 155
var PC = new THREE.Vector3().copy(P0).sub(PC_X);
не соответствует моему
PC=P0-(Y0*r);
у вас другая ось и нет радиуса если ваши оси имеют другое значение, чем мое, тогда вы просто поменяете X,Y,Z
соответственно, но вам все равно нужно использовать радиус. Это позиция, если центр изгиба, так что если неправильно вычислен, изгиб тоже неправильный ... Используемая ось должна быть не той, вокруг которой выполняется вращение, а не высотой цилиндра.
по строке 173
var p = new THREE.Vector3().copy(X0);
p.multiplyScalar(slice_arc_length[j]-l0);
Я получил:
p=Z0*(len1[j]-l0);
так явно другая ось снова. Вы должны использовать высоту оси цилиндра ... То же самое относится и к остальному в строке 180.
Так что, если я правильно понял, это соответствие оси
mine yours meaning
X0 Z0 bending rotation axis
Y0 X0
Z0 Y0 cylinder height
строка 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] другое сравнение
строка 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] другое сравнение
Вы повторяете одни и те же ошибки снова и снова ... неправильно переписываете уравнения, так что никакой мозг не работает правильно. На этот раз:
В строке 186:
var point_temp = new THREE.Vector3().copy(slices[j][i]);
Вы забыли добавить 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
, проверенные не для rotatez
... две версии просто вращаются в противоположных направлениях, поэтому обе верны, но код может корректно работать только с одной.
угловые единицы
изгиб средней линии (той, которую вы получили «правильно» в коде) не похож на поворот вокруг PC
, это может быть вызвано # 2 , но это также может быть вызвано неправильными угловыми единицами , Ваши функции cos
и sin
нуждаются в [deg]
или [rad]
? В настоящее время все рассчитанные углы приведены в [rad]
.