PDA

View Full Version : how to draw a heavy coiled spring?



jyoung77
05-04-2007, 10:48 PM
Hi,

Can someone kindly show me how to draw a heavy coiled spring (like a broken donut spiraled)? I know how to draw a light coiled spring, which is basically a coiled line. Hopefully I don't have to tessellate it unless it's the only resort. Any help is much appreciated.

Tony

Jon Leech (oddhack)
05-05-2007, 06:20 PM
Try Linas Vesptas' GLE Tubing & Extrusion Library (http://sourceforge.net/projects/gle/) .

dorbie
05-07-2007, 01:51 AM
You have to tesselate it.

You need to sweep a circle around a helix.

1) Generate the points for a circle.
2) Translate this out along an axis.
3) Rotate about the origin some parameterized amount.
4) Translate upwards by some small parameterized amount.
5) Increase parameterized amount and goto 1

This will points which you then either render or mexh.

You can render as you go but it ain't essential.

Here's some code I wrote to draw a torus, copy it and add a translation (stage 4 above). It also has tangent & binormals & other stuff which you probably don't need.

I just ripped it out of an old project I had with some editing but it should be very close to useable in your program.


#define MINOR_DIV 32
#define MAJOR_DIV 48
#define RadiusMajor 23.0f
#define RadiusMinor 6.0f
#define RepeatsMajor 10.0f
#define RepeatsMinor 4.0f
void DrawTorus(float lod_bias, int numpasses, int pass)
{
float minor_x, minor_z;
double major_inc, minor_inc;
double r_minor, r_major;
double sin_major1, cos_major1, sin_major2, cos_major2;
float deltas, deltat;

static float vert[6*(MAJOR_DIV)*(MINOR_DIV+1)];
static float norm[6*(MAJOR_DIV+2)*(MINOR_DIV+1)];
int vert_pos = 0;
static float tex[4*(MAJOR_DIV)*(MINOR_DIV+1)];

int tex_pos = 0;
static float tangent[8*(MAJOR_DIV)*(MINOR_DIV+1)];
static float binorm[8*(MAJOR_DIV)*(MINOR_DIV+1)];
int tangent_pos = 0;
int maj_pos, min_pos;
static int first = 1;
float tex_shift[4*(MAJOR_DIV)*(MINOR_DIV+1)];
float brightness = 1.0f/numpasses;
float VdotN, VprojB, VprojT;
float tmp_vec[3];
float pass_mult;
float Ts, Bs;


major_inc = M_PI*2/MAJOR_DIV;
minor_inc = M_PI*2/MINOR_DIV;


if(first)
{
first = 0;
for (r_major = 0.0f; r_major <= M_PI*2.0-.000001; r_major += major_inc)
{
sin_major1 = sin(r_major);
cos_major1 = cos(r_major);
sin_major2 = sin(r_major+major_inc);
cos_major2 = cos(r_major+major_inc);

for(r_minor = 0.0f; r_minor < M_PI*2.0+.000001; r_minor += minor_inc)
{
minor_x = RadiusMinor*(float)sin(r_minor);
minor_z = RadiusMinor*(float)cos(r_minor);

tex[tex_pos++] = (RepeatsMajor/2.0f) * (float)(r_major/M_PI);
tex[tex_pos++] = 0.5f + (RepeatsMinor/2.0f) * (float)(r_minor/M_PI);

tangent[tangent_pos++] = 0.0f;
tangent[tangent_pos++] = (float)-cos_major1;
tangent[tangent_pos++] = (float)sin_major1;
// texture repeats per unit = repeats / Pi*diameter
binorm[tangent_pos] = RepeatsMinor / ((float)M_PI * (RadiusMinor + RadiusMinor));
tangent[tangent_pos++] = RepeatsMajor / ((float)-M_PI * ((minor_z-RadiusMajor) + (minor_z-RadiusMajor)));

Normalize(tangent+tangent_pos-4);

norm[vert_pos] = minor_x;
vert[vert_pos++] = minor_x;
norm[vert_pos] = (float)sin_major1*minor_z;
vert[vert_pos++] = (float)sin_major1*(minor_z-RadiusMajor);
norm[vert_pos] = (float)cos_major1*minor_z;
vert[vert_pos++] = (float)cos_major1*(minor_z-RadiusMajor);
Normalize(norm+vert_pos-3);

Cross(binorm+tangent_pos-4, norm+vert_pos-3, tangent+tangent_pos-4);

tex[tex_pos++] = (RepeatsMajor/2.0f) * (float)((r_major+major_inc)/M_PI);
tex[tex_pos++] = 0.5f + (RepeatsMinor/2.0f) * (float)(r_minor/M_PI);

tangent[tangent_pos++] = 0.0f;
tangent[tangent_pos++] = (float)-cos_major2;
tangent[tangent_pos++] = (float)sin_major2;
// texture repeats per unit = repeats / Pi*diameter
binorm[tangent_pos] = RepeatsMinor / ((float)M_PI * (RadiusMinor + RadiusMinor));
tangent[tangent_pos++] = RepeatsMajor / ((float)-M_PI * ((minor_z-RadiusMajor) + (minor_z-RadiusMajor)));

Normalize(tangent+tangent_pos-4);

norm[vert_pos] = minor_x;
vert[vert_pos++] = minor_x;
norm[vert_pos] = (float)sin_major2*minor_z;
vert[vert_pos++] = (float)sin_major2*(minor_z-RadiusMajor);
norm[vert_pos] = (float)cos_major2*minor_z;
vert[vert_pos++] = (float)cos_major2*(minor_z-RadiusMajor);
Normalize(norm+vert_pos-3);

Cross(binorm+tangent_pos-4, norm+vert_pos-3, tangent+tangent_pos-4);

}

}
}


glEnable(GL_TEXTURE_2D);

if(wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

vert_pos = 0;
for(maj_pos = 0; maj_pos < MAJOR_DIV; maj_pos++)
{
glBegin(GL_TRIANGLE_STRIP);
for(min_pos = 0; min_pos <= MINOR_DIV; min_pos++)
{
glTexCoord2f(tex_shift[vert_pos*4], tex_shift[vert_pos*4+1]);
glNormal3f(norm[vert_pos*6], norm[vert_pos*6+1], norm[vert_pos*6+2]);
glVertex3f(vert[vert_pos*6], vert[vert_pos*6+1], vert[vert_pos*6+2]);

glTexCoord2f(tex_shift[vert_pos*4+2], tex_shift[vert_pos*4+3]);
glNormal3f(norm[vert_pos*6+3], norm[vert_pos*6+4], norm[vert_pos*6+5]);
glVertex3f(vert[vert_pos*6+3], vert[vert_pos*6+4], vert[vert_pos*6+5]);

vert_pos ++;
}
glEnd();
}

if(wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glDisable(GL_TEXTURE_2D);


if(hedgehog &amp;&amp; pass == numpasses)
{
// draws normal, tangent and binormal vectors
// different sides of mesh get drawn two shades with displacement
// this is to verify matching normals on adjacent meshes
vert_pos = 0;
for(maj_pos = 0; maj_pos < MAJOR_DIV; maj_pos++)
{
glBegin(GL_LINES);
for(min_pos = 0; min_pos <= MINOR_DIV; min_pos++)
{
// Ts & Bs can be used scale the coordinate frame to texture space,
// scale is stored in 4th component
Ts = 1.0f;// /tangent[vert_pos*8+3];
Bs = 1.0f;// /binorm[vert_pos*8+3];

// normal
glColor3f(0.5, 0.0, 0.0);
glVertex3f(vert[vert_pos*6], vert[vert_pos*6+1], vert[vert_pos*6+2]);
glVertex3f(vert[vert_pos*6]+norm[vert_pos*6]*.5f, vert[vert_pos*6+1]+norm[vert_pos*6+1]*.5f, vert[vert_pos*6+2]+norm[vert_pos*6+2]*.5f);

glColor3f(1.0, 0.0, 0.0);
glVertex3f(vert[vert_pos*6+3]+norm[vert_pos*6+3]*.5f, vert[vert_pos*6+4]+norm[vert_pos*6+4]*.5f, vert[vert_pos*6+5]+norm[vert_pos*6+5]*.5f);
glVertex3f(vert[vert_pos*6+3]+norm[vert_pos*6+3], vert[vert_pos*6+4]+norm[vert_pos*6+4], vert[vert_pos*6+5]+norm[vert_pos*6+5]);

// tangent
glColor3f(0.0, 0.5, 0.0);
glVertex3f(vert[vert_pos*6], vert[vert_pos*6+1], vert[vert_pos*6+2]);
glVertex3f(vert[vert_pos*6]+tangent[vert_pos*8]*.5f*Ts, vert[vert_pos*6+1]+tangent[vert_pos*8+1]*.5f*Ts, vert[vert_pos*6+2]+tangent[vert_pos*8+2]*.5f*Ts);

glColor3f(0.0, 1.0, 0.0);
glVertex3f(vert[vert_pos*6+3]+tangent[vert_pos*8+4]*.5f*Ts, vert[vert_pos*6+4]+tangent[vert_pos*8+5]*.5f*Ts, vert[vert_pos*6+5]+tangent[vert_pos*8+6]*.5f*Ts);
glVertex3f(vert[vert_pos*6+3]+tangent[vert_pos*8+4]*Ts, vert[vert_pos*6+4]+tangent[vert_pos*8+5]*Ts, vert[vert_pos*6+5]+tangent[vert_pos*8+6]*Ts);

// binormal
glColor3f(0.0, 0.0, 0.5);
glVertex3f(vert[vert_pos*6], vert[vert_pos*6+1], vert[vert_pos*6+2]);
glVertex3f(vert[vert_pos*6]+binorm[vert_pos*8]*.5f*Bs, vert[vert_pos*6+1]+binorm[vert_pos*8+1]*.5f*Bs, vert[vert_pos*6+2]+binorm[vert_pos*8+2]*.5f*Bs);

glColor3f(0.0, 0.0, 1.0);
glVertex3f(vert[vert_pos*6+3]+binorm[vert_pos*8+4]*.5f*Bs, vert[vert_pos*6+4]+binorm[vert_pos*8+5]*.5f*Bs, vert[vert_pos*6+5]+binorm[vert_pos*8+6]*.5f*Bs);
glVertex3f(vert[vert_pos*6+3]+binorm[vert_pos*8+4]*Bs, vert[vert_pos*6+4]+binorm[vert_pos*8+5]*Bs, vert[vert_pos*6+5]+binorm[vert_pos*8+6]*Bs);

vert_pos ++;
}
glEnd();


}

}
}

dorbie
05-07-2007, 01:54 AM
P.S. it needs these:


void Normalize(float *ptr)
{
float length = 0;

length = (float)sqrt((double)*ptr * *ptr + *(ptr+1) * *(ptr+1) + *(ptr+2) * *(ptr+2) );
*(ptr) /= length;
*(ptr+1) /= length;
*(ptr+2) /= length;


}

void Cross(float *destination, float *ptr1, float *ptr2)
{
*(destination) = *(ptr1+1) * *(ptr2+2) - *(ptr1+2) * *(ptr2+1);
*(destination+1) = *(ptr1+2) * *ptr2 - *ptr1 * *(ptr2+2);
*(destination+2) = *ptr1 * *(ptr2+1) - *(ptr1+1) * *ptr2;
}

float Dot(float *ptr1, float *ptr2)
{

return ( *ptr1 * *ptr2 + *(ptr1+1) * *(ptr2+1) + *(ptr1+2) * *(ptr2+2) );

}

jyoung77
05-07-2007, 12:06 PM
Hi Dorbie,

Thanks so much for your sharing. I will be trying today. Thanks again.

Tony