将一个立方体变形为三个js

时间:2016-01-27 09:01:01

标签: three.js geometry tween.js morphing

我试图将three.jstween.js变成一个细长的立方体变形为线圈。我已经搜索过已经问过的问题,但没有一个问题可以指导我。

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

cube to coil

1 个答案:

答案 0 :(得分:0)

  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增加一些步骤......

  5. [edit1] 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);
    

    正如你所看到的,一半的正弦波被忽略了,所以你可以有时间在没有螺丝的情况下真正看到管子。这里用照明输出:

    helix

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

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