gpt4 book ai didi

three.js - 用三个 js 将立方体变形为线圈

转载 作者:行者123 更新时间:2023-12-03 01:57:33 26 4
gpt4 key购买 nike

我尝试通过third.jstween.js将薄矩形立方体变形为线圈 。我搜索了已经有人提出的问题,但没有一个能指导我。

我应该使用哪种变形函数,以及如何创建线圈形状?

cube to coil

最佳答案

  1. 将试管存储为一组 N

    您需要每个(圆形)切片的中心点和法线向量。

    const int N=128;
    struct slice { float p[3],n[3]; };
    slice mesh[N];

    在开始时将其初始化为管(与 y 轴对齐)

    for (int i=0;i<N;i++)
    {
    mesh[i].p[0]= 0.0;
    mesh[i].p[1]=-1.0+2.0*float(i)/float(N-1);
    mesh[i].p[2]= 0.0;
    mesh[i].n[0]= 0.0;
    mesh[i].n[1]=+1.0;
    mesh[i].n[2]= 0.0;
    }
  2. 为此类网格表示编写可视化代码

    您需要获取每个切片的圆周点,并将它们与 QUAD_STRIP 或用于管表面的任何基元连接起来。顶部和底部最好以 TRIANGLE_FAN 围绕中心点。

    您可以通过我的glCircle3D in C++获取积分只需根据需要存储/使用它们,而不是绘制它们...

  3. 在管和螺旋之间插值

    如果上述方法有效,您可以将中心位置和法线变成具有可变半径r和固定螺钉m的螺旋。所以我会尝试:

    float a=6.283185307179586476925286766559*float(i*m)/float(N-1);
    mesh[i].p[0] = r*cos(a);
    mesh[i].p[2] = r*sin(a);

    法线可以类似地计算,但我现在没有时间测试它,而且我的想象力不太好,所以我会这样做:

    mesh[i].n[0] = mesh[i].p[0] - mesh[i-1].p[0];
    mesh[i].n[1] = mesh[i].p[1] - mesh[i-1].p[1];
    mesh[i].n[2] = mesh[i].p[2] - mesh[i-1].p[2];
    normalize(mesh[i].n); // set to unit vector

    只需将法线从切片 1 复制到切片 0 就可以了。

  4. 动画

    只需将 r 从零更改为某个 R 即可对网格进行动画处理。如果你想要连续的效果,你可以这样做r=R*sin(t),其中t随着某个步骤而增加...

[编辑1] C++ OpenGL 示例

如果将以上所有内容放在一起,您应该得到如下结果:

//---------------------------------------------------------------------------
// height ,tube r ,screw r ,screws
void helix(double h,double r,double R,double N)
{
int i,j,na;
double pos[3]={ 0.0,0.0,0.0 },x[3],y[3],
nor[3]={ 0.0,1.0,0.0 },ss,dy,a,da,b,db;
na=double(N*36.0); // 36 slices per screw
const int nb=36+1; // 36 points per circle slice
dy=h/double(na); // y axis step
da=2.0*M_PI*N/double(na); // screw angle step
db=2.0*M_PI/double(nb-1); // slice circle angle step
ss=1.0/sqrt((R*R)+(dy*dy)); // normalization scale
double pnt[nb*12],*p0=pnt,*p1=pnt+(nb*6),*pp; // 2 slice point buffers (normal3d+vertex3d)*nb*2 = 12*nb
for (a=0.0,i=0;i<na;i++,a+=da)
{
if (a>2.0*M_PI) a-=2.0*M_PI;
// slice center
pos[0]=R*cos(a);
pos[1]+=dy;
pos[2]=R*sin(a);
// slice normal
nor[0]=-ss*R*sin(a);
nor[1]=+ss*dy;
nor[2]=+ss*R*cos(a);
// slice basis vectors x,y
x[0]=cos(a);
x[1]=0.0;
x[2]=sin(a);
// y = cross(x,nor)
y[0]= -(x[2]*nor[1]);
y[1]=(x[2]*nor[0])-(x[0]*nor[2]);
y[2]=(x[0]*nor[1]);
// get the slice points (remember 2 slices for QUAD STRIP) to actual point buffer p1
for (pp=p1,b=0.0,j=0;j<nb;j++,b+=db,pp+=6)
{
// normal
pp[0]=(x[0]*cos(b))+(y[0]*sin(b));
pp[1]=(x[1]*cos(b))+(y[1]*sin(b));
pp[2]=(x[2]*cos(b))+(y[2]*sin(b));
// position
pp[3]=pos[0]+(pp[0]*r);
pp[4]=pos[1]+(pp[1]*r);
pp[5]=pos[2]+(pp[2]*r);
}
// if 2 slices done render the slice between last slice p0 and actual slice p1
glBegin(GL_QUAD_STRIP);
if (i) for (j=0;j<6*nb;j+=6)
{
glNormal3dv(p0+j+0);
glVertex3dv(p0+j+3);
glNormal3dv(p1+j+0);
glVertex3dv(p1+j+3);
}
glEnd();
// swap last,actual slice point buffers p0 <-> p1
pp=p0; p0=p1; p1=pp;
}
}
//---------------------------------------------------------------------------

它在 OpenGL 中渲染螺旋。它从 (0,0,0) 开始,到 (0,h,0) 结束,其中:

  • r 是管的半径
  • R 是螺钉的半径
  • h 是螺旋高度/大小
  • N 是每h 的螺钉数量

它会生成顶点和法线信息,以便您可以使用照明。对于动画我用这个:

static double t=0.0; t+=0.1; if (t>=pi2) t-=pi2;
double R=sin(t); if (R<0.0) R=0.0;
glColor3f(1.0,1.0,1.0); helix(1.0,0.05,0.3*R,6.0);

正如您所看到的,一半的正弦波被忽略,因此您可以有时间实际查看没有螺丝的 pipe 。这里输出带照明:

helix

左侧是旋开的 pipe (R=0)。右边是完全变形的螺丝,中间是介于两者之间的东西。

PS 如果您想让变形更有趣,您还可以将 N 参数从 0 动画化为某个常量。

关于three.js - 用三个 js 将立方体变形为线圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35032812/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com