将一个立方体变形为三个 js 中的线圈 [英] Morph a cube to coil in three js
问题描述
我尝试通过 three.js
和 tween.js
将细长的矩形 cube 变形为 coil.我搜索了已经提出的问题,但没有一个能指导我.
我应该使用哪个变形函数,如何创建线圈形状?
将您的试管存储为一组
N
个切片您需要每个(圆形)切片的中心点和法线向量.
const int N=128;结构切片 { 浮动 p[3],n[3];};切片网格[N];
在开始时将其初始化到管子(与 y 轴对齐)
for (int i=0;i
为这种网格表示编写可视化代码
您需要获取每个切片的圆周点并将它们与 QUAD_STRIP 或您用于管表面的任何图元连接起来.顶部和底部最好以 TRIANGLE_FAN 为中心点.
您可以使用我的
左边是旋开的管子 (
R=0
).右边是完全变形的螺丝,中间是介于两者之间的东西.PS 如果您想让变形更有趣,您还可以将
N
参数从0
设置为某个常数.I have tried to morph a thin rectangular cube to coil by
three.js
andtween.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?
解决方案have your tube stored as a set of
N
slicesYou 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; }
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 ...
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 screwsm
. 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.
animate
Just animate the mesh with changing
r
from zero to someR
. If you want continuous effect you can dor=R*sin(t)
wheret
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 tubeR
is the radius of the screwsh
is helix height/sizeN
is number of screws perh
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 from0
to some constant.这篇关于将一个立方体变形为三个 js 中的线圈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!