变形一个立方体以三个js卷绕 [英] Morph a cube to coil in three js

查看:132
本文介绍了变形一个立方体以三个js卷绕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过 three.js 和<$ c $将变薄的矩形立方体变形为线圈 C> tween.js 。我已经搜索了已经被问过的问题,但没有一个人指导我。



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

解决方案


  1. 将您的信息存储为一组 N 切片



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

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

    在开始时将其初始化(与y轴对齐)
    $ (int i = 0; i< N; i ++)
    {
    mesh [i] .p {b $ b

      [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的中心点附近。



    您可以使用我的

    左边是松开的管( R = 0 )。右边是完全变形的螺丝,中间是中间的东西。



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

    I have tried to morph a thin rectangular cube to coil by three.js and tween.js. I've searched questions that already has been ask but none of them guide me.

    Which morph function should I use, and how can I create a coil shape?

    解决方案

    1. have your tube stored as a set of N slices

      You need center point and normal vector for each (circle) slice.

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

      Init it to tube at start (aligned to y axis)

      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. write visualization code for such mesh representation

      You need to obtain the circumference points of each slice and join them with QUAD_STRIP or what ever primitive you are using for the tube surface. The top and bottom is best with TRIANGLE_FAN around center point.

      You can obtain the points with my glCircle3D in C++ just instead of drawing them store/use them as you need ...

    3. interpolate between tube and helix

      If the above is workung you can turn the centers position and normals into helix with variable radius r and fixed screws m. So I would try:

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

      The normal can be computed similary but I do not have the time for testing it right now and my imagination is not that good so i would instead do this:

      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
      

      Just copy the normal from slice 1 to slice 0 and you should be fine.

    4. animate

      Just animate the mesh with changing r from zero to some R. If you want continuous effect you can do r=R*sin(t) where t is increasing with some step ...

    [edit1] C++ OpenGL example

    If you put all the above together you should get something like this:

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

    Which renders helix in OpenGL. it starts from (0,0,0) and ends in (0,h,0)where:

    • r is the radius of the tube
    • R is the radius of the screws
    • h is helix height/size
    • N is number of screws per h

    It generates Vertex and Normal info so you can use lighting. for animation I use this:

    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);
    

    As you can see half of the sin wave is neglected so you can have time to actually see the tube without the screws. Here output with lighting:

    On the left is the unscrewed tube (R=0). On the right is fully morphed screw and in the middle is something in between.

    PS if you want to make the morph more interesting you can also animate the N parameter from 0 to some constant.

    这篇关于变形一个立方体以三个js卷绕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆