Open GL Super Bible

Previous Table of Contents Next


The Thread

The thread is the most complex part of the bolt. Itís composed of two planes arranged in a V shape that follows a corkscrew pattern up the length of the shaft. It is created as two flat segments arranged in a V pattern. Figure 10-6 illustrates the triangle outline of this shape and Listing 10-6 is the OpenGL code used to produce this shape.


Figure 10-6  Progression of triangle outline of thread

Listing 10-6 Rendering the thread of the bolt

// Creates the thread of the bolt
void RenderThread(void)
        {
        float x,y,z,angle;             // Calculate coordinates and step
                                        angle
        float height = 75.0f;          // Height of the threading
        float diameter = 20.0f;        // Diameter of the threading
        float normal[3],corners[4][3]; // Storage for normal and corners
        float step = (3.1415f/32.0f);  // One revolution
        float revolutions = 7.0f;      // How many times around the shaft
        float threadWidth = 2.0f;      // How wide is the thread
        float threadThick = 3.0f;      // How thick is the thread
        float zstep = .125f;           // How much does the thread move up
                                       // the z axis each time a new
                                        segment
                                       // is drawn.
        // 360 degrees in radians
        #define PI2 (2.0f*3.1415f)

        // Set material color for thread
        glColor3f(0.0f, 0.0f, 0.4f);


        z = -height+2;// Starting spot almost to the end

        // Go around and draw the sides until finished spinning up
        for(angle = 0.0f; angle < PI2*revolutions; angle += step)
                {
                // Calculate x and y position of the next vertex
                x = diameter*(float)sin(angle);
                y = diameter*(float)cos(angle);

                // Store the next vertex next to the shaft
                corners[0][0] = x;
                corners[0][1] = y;
                corners[0][2] = z;

                // Calculate the position away from the shaft
                x = (diameter+threadWidth)*(float)sin(angle);
                y = (diameter+threadWidth)*(float)cos(angle);

                corners[1][0] = x;
                corners[1][1] = y;
                corners[1][2] = z;

                // Calculate the next position away from the shaft
                x = (diameter+threadWidth)*(float)sin(angle+step);
                y = (diameter+threadWidth)*(float)cos(angle+step);

                corners[2][0] = x;
                corners[2][1] = y;
                corners[2][2] = z + zstep;

                // Calculate the next position along the shaft
                x = (diameter)*(float)sin(angle+step);
                y = (diameter)*(float)cos(angle+step);

                corners[3][0] = x;
                corners[3][1] = y;
                corners[3][2] = z+ zstep;

                // We'll be using triangles, so make 
                // counterclockwise polygons face out
                glFrontFace(GL_CCW);
                glBegin(GL_TRIANGLES);// Start the top section of thread

                        // Calculate the normal for this segment
                        calcNormal(corners, normal);
                        glNormal3fv(normal);

                        // Draw two triangles to cover area
                        glVertex3fv(corners[0]);
                        glVertex3fv(corners[1]);
                        glVertex3fv(corners[2]);

                        glVertex3fv(corners[2]);
                        glVertex3fv(corners[3]);
                        glVertex3fv(corners[0]);

                glEnd();

                // Move the edge along the shaft slightly up the z axis
                // to represent the bottom of the thread
                corners[0][2] += threadThick;
                corners[3][2] += threadThick;

                // Recalculate the normal since points have changed. This
                // time it points in the opposite direction, so reverse it
                calcNormal(corners, normal);
                normal[0] = -normal[0];
                normal[1] = -normal[1];
                normal[2] = -normal[2];

                // Switch to clockwise facing out for underside of the
                // thread.
                glFrontFace(GL_CW);

                // Draw the two triangles
                glBegin(GL_TRIANGLES);
                        glNormal3fv(normal);

                        glVertex3fv(corners[0]);
                        glVertex3fv(corners[1]);
                        glVertex3fv(corners[2]);

                        glVertex3fv(corners[2]);
                        glVertex3fv(corners[3]);
                        glVertex3fv(corners[0]);

        glEnd();

        // Creep up the z axis
        z += zstep;
        }
}

Figure 10-7 shows the output of the THREAD program.


Figure 10-7  Output from the THREAD program

Putting the Model Together

The bolt is assembled by drawing all three sections in their appropriate location. All sections are translated appropriately up the z-axis. The shaft and threads are translated the same amount because essentially they occupy the same location. All that needs to be done is to put the pieces in the appropriate locations, and hidden surface removal will automatically eliminate hidden surfaces for us.

Listing 10-7 is the rendering code that manipulates and renders the three bolt components. Figure 10-8 shows the final output of the BOLT program.

Listing 10-7 Rendering code to draw the completed bolt

// Called to draw the entire bolt
void RenderScene(void)
        {
        // Clear the window with current clearing color
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Save the matrix state and do the rotations
        glMatrixMode(GL_MODELVIEW);

        // Rotate and translate, then render the bolt head
        glPushMatrix();
                glRotatef(xRot, 1.0f, 0.0f, 0.0f);
                glRotatef(yRot, 0.0f, 1.0f, 0.0f);
                glTranslatef(0.0f, 0.0f, 55.0f);
                RenderHead();
        glPopMatrix();


        // Save matrix state, rotate, translate and draw the
        // shaft and thread together
        glPushMatrix();
        glRotatef(xRot, 1.0f, 0.0f, 0.0f);
        glRotatef(yRot, 0.0f, 1.0f, 0.0f);
        glTranslatef(0.0f, 0.0f, 40.0f);

        // Render just the hexagonal head of the nut
        RenderShaft();
        RenderThread();

        glPopMatrix();

        // Flush drawing commands
        glFlush();


Figure 10-8  Output from the BOLT program


Previous Table of Contents Next