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?
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?
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;
}
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 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.
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 tubeR
is the radius of the screwsh
is helix height/sizeN
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.
© 2022 - 2024 — McMap. All rights reserved.
Cube->Coil
instead ofTube->Coil
which I obviously overlooked) And as this is still not accepted Do you really need the cube? (your image suggest tube) if yes the coil should have circular cut or square cut of the wire ? – Expound