Выбрать главу

}

The following routine just sets up a point of view using gluLookAt. We set a point of view placed at 0, 5, 50 that is looking to 0, 0, 0 and that has the UP vector looking UP (0, 1, 0)! :D

void ProcessHelix() // Draws A Helix

{

 GLfloat x; // Helix x Coordinate

 GLfloat y; // Helix y Coordinate

 GLfloat z; // Helix z Coordinate

 GLfloat phi; // Angle

 GLfloat theta; // Angle

 GLfloat v,u; // Angles

 GLfloat r; // Radius Of Twist

int twists = 5; // 5 Twists

 GLfloat glfMaterialColor[]={0.4f,0.2f,0.8f,1.0f}; // Set The Material Color

 GLfloat specular[]={1.0f,1.0f,1.0f,1.0f}; // Sets Up Specular Lighting

 glLoadIdentity(); // Reset The Modelview Matrix

 gluLookAt(0, 5, 50, 0, 0, 0, 0, 1, 0); // Eye Position (0,5,50) Center Of Scene (0,0,0)

 // Up On Y Axis.

 glPushMatrix(); // Push The Modelview Matrix

 glTranslatef(0,0,-50); // Translate 50 Units Into The Screen

 glRotatef(angle/2.0f,1,0,0); // Rotate By angle/2 On The X-Axis

 glRotatef(angle/3.0f,0,1,0); // Rotate By angle/3 On The Y-Axis

 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glfMaterialColor);

 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);

We then calculate the helix formula and render the spring. It's quite simple, I won't explain it, beacuse it isn't the main goal of this tutorial. The helix code was borrowed (and optimized a bit) from Listen Software friends. This is written the simple way, and is not the fastest method. Using vertex arrays would make it faster!

 r=1.5f; // Radius

 glBegin(GL_QUADS); // Begin Drawing Quads

 for(phi=0; phi <= 360; phi+=20.0) // 360 Degrees In Steps Of 20

 {

  for(theta=0; theta<=360*twists; theta+=20.0) // 360 Degrees * Number Of Twists In Steps Of 20

  {

   v=(phi/180.0f*3.142f); // Calculate Angle Of First Point ( 0 )

   u=(theta/180.0f*3.142f); // Calculate Angle Of First Point ( 0 )

   x=float(cos(u)*(2.0f+cos(v) ))*r; // Calculate x Position (1st Point)

   y=float(sin(u)*(2.0f+cos(v) ))*r; // Calculate y Position (1st Point)

   z=float((( u-(2.0f*3.142f)) + sin(v) ) * r); // Calculate z Position (1st Point)

   vertexes[0][0]=x; // Set x Value Of First Vertex

   vertexes[0][1]=y; // Set y Value Of First Vertex

   vertexes[0][2]=z; // Set z Value Of First Vertex

   v=(phi/180.0f*3.142f); // Calculate Angle Of Second Point ( 0 )

   u=((theta+20)/180.0f*3.142f); // Calculate Angle Of Second Point ( 20 )

   x=float(cos(u)*(2.0f+cos(v) ))*r; // Calculate x Position (2nd Point)

   y=float(sin(u)*(2.0f+cos(v) ))*r; // Calculate y Position (2nd Point)

   z=float((( u-(2.0f*3.142f)) + sin(v) ) * r); // Calculate z Position (2nd Point)

   vertexes[1][0]=x; // Set x Value Of Second Vertex

   vertexes[1][1]=y; // Set y Value Of Second Vertex

   vertexes[1][2]=z; // Set z Value Of Second Vertex

   v=((phi+20)/180.0f*3.142f); // Calculate Angle Of Third Point ( 20 )

   u=((theta+20)/180.0f*3.142f); // Calculate Angle Of Third Point ( 20 )

   x=float(cos(u)*(2.0f+cos(v) ))*r; // Calculate x Position (3rd Point)

   y=float(sin(u)*(2.0f+cos(v) ))*r; // Calculate y Position (3rd Point)

   z=float((( u-(2.0f*3.142f)) + sin(v) ) * r); // Calculate z Position (3rd Point)

   vertexes[2][0]=x; // Set x Value Of Third Vertex

   vertexes[2][1]=y; // Set y Value Of Third Vertex

   vertexes[2][2]=z; // Set z Value Of Third Vertex

   v=((phi+20)/180.0f*3.142f); // Calculate Angle Of Fourth Point ( 20 )

   u=((theta)/180.0f*3.142f); // Calculate Angle Of Fourth Point ( 0 )

   x=float(cos(u)*(2.0f+cos(v) ))*r; // Calculate x Position (4th Point)

   y=float(sin(u)*(2.0f+cos(v) ))*r; // Calculate y Position (4th Point)

   z=float((( u-(2.0f*3.142f)) + sin(v) ) * r); // Calculate z Position (4th Point)

   vertexes[3][0]=x; // Set x Value Of Fourth Vertex

   vertexes[3][1]=y; // Set y Value Of Fourth Vertex

   vertexes[3][2]=z; // Set z Value Of Fourth Vertex

   calcNormal(vertexes,normal); // Calculate The Quad Normal

   glNormal3f(normal[0],normal[1],normal[2]); // Set The Normal

   // Render The Quad

   glVertex3f(vertexes[0][0],vertexes[0][1],vertexes[0][2]);

   glVertex3f(vertexes[1][0],vertexes[1][1],vertexes[1][2]);

   glVertex3f(vertexes[2][0],vertexes[2][1],vertexes[2][2]);

   glVertex3f(vertexes[3][0],vertexes[3][1],vertexes[3][2]);

  }

 }

 glEnd(); // Done Rendering Quads

 glPopMatrix(); // Pop The Matrix

}

This two routines (ViewOrtho and ViewPerspective) were coded to make it easy to draw in an orthogonal way and get back to perspective rendering with ease.

ViewOrtho simply sets the projection matrix, then pushes a copy of the actual projection matrix onto the OpenGL stack. The identity matrix is then loaded and an orthographic view with the current screen resolution is set up.

This way it is possible to draw using 2D coordinates with 0,0 in the upper left corner of the screen and with 640,480 in the lower right corner of the screen.

Finally, the modelview matrix is activated for rendering stuff.

ViewPerspective sets up projection matrix mode and pops back the non-orthogonal matrix that ViewOrtho pushed onto the stack. The modelview matrix is then selected so we can rendering stuff.

I suggest you keep these two procedures, it's nice being able to render in 2D without having to worry about the projection matrix!

void ViewOrtho() // Set Up An Ortho View

{

 glMatrixMode(GL_PROJECTION); // Select Projection

 glPushMatrix(); // Push The Matrix

 glLoadIdentity(); // Reset The Matrix

 glOrtho( 0, 640 , 480 , 0, –1, 1 ); // Select Ortho Mode (640x480)

 glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix

 glPushMatrix(); // Push The Matrix

 glLoadIdentity(); // Reset The Matrix

}

void ViewPerspective() // Set Up A Perspective View

{

 glMatrixMode( GL_PROJECTION ); // Select Projection

 glPopMatrix(); // Pop The Matrix

 glMatrixMode( GL_MODELVIEW ); // Select Modelview

 glPopMatrix(); // Pop The Matrix

}

Now it's time to explain how the fake radial blur effect is done:

We need to draw the scene so it appears blurred in all directions starting from the center. The trick is doing this without a major performance hit. We can't read and write pixels, and if we want compatibility with non kick-butt video cards, we can't use extensions or driver specific commands.