Tricks of the Windows Game Programming Gurus:Vector Rasterization and 2D Transformations

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

Finally, while we’re on the subject of trivial rejection and tests, we need to address all the degenerate cases of a triangle, such as a single point and a straight horizontal or vertical line. The code should test for these cases without blowing up! And of course, you can’t assume that the vertices are in the correct order when sent to the function, so you’ll sort them top to bottom, left to right. That way you’ll have a known starting point. With all that in mind, here are the three functions that make up your 8-bit triangle drawing engine.

This function draws a triangle with a flat top:

    void Draw_Top_Tri(int x1,int y1,

                      int x2,int y2,

                      int x3,int y3,

                      int color,

                      UCHAR *dest_buffer, int mempitch)

    {

    // this function draws a triangle that has a flat top

    float dx_right,    // the dx/dy ratio of the right edge of line

          dx_left,     // the dx/dy ratio of the left edge of line

          xs,xe,       // the starting and ending points of the edges

          height;      // the height of the triangle

    int temp_x,        // used during sorting as temps

        temp_y,

        right,         // used by clipping

        left;

    // destination address of next scanline

    UCHAR  *dest_addr = NULL;

    // test order of x1 and x2

    if (x2 < x1)

       {

       temp_x = x2;

       x2     = x1;

       x1     = temp_x;

       } // end if swap

    // compute delta’s

    height = y3-y1;

    dx_left  = (x3-x1)/height;

    dx_right = (x3-x2)/height;

    // set starting points

    xs = (float)x1;

    xe = (float)x2+(float)0.5;

    // perform y clipping

    if (y1 < min_clip_y)

       {

       // compute new xs and ys

       xs = xs+dx_left*(float)(-y1+min_clip_y);

       xe = xe+dx_right*(float)(-y1+min_clip_y);

       // reset y1

       y1=min_clip_y;

       } // end if top is off screen

    if (y3>max_clip_y)

       y3=max_clip_y;

    // compute starting address in video memory

    dest_addr = dest_buffer+y1*mempitch;

    // test if x clipping is needed

    if (x1>=min_clip_x && x1<=max_clip_x &&

        x2>=min_clip_x && x2<=max_clip_x &&

        x3>=min_clip_x && x3<=max_clip_x)

        {

        // draw the triangle

        for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)

            {

            memset((UCHAR *)dest_addr+(unsigned int)xs,

                    color,(unsigned int)(xe-xs+1));

            // adjust starting point and ending point

            xs+=dx_left;

            xe+=dx_right;

            } // end for

        } // end if no x clipping needed

    else

       {

       // clip x axis with slower version

       // draw the triangle

       for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)

           {

           // do x clip

           left  = (int)xs;

           right = (int)xe;

           // adjust starting point and ending point

           xs+=dx_left;

           xe+=dx_right;

    <s$I∼graphics;triangles;drawing>

           // clip line

           if (left < min_clip_x)

              {

              left = min_clip_x;

              if (right < min_clip_x)

                 continue;

              }

           if (right > max_clip_x)

              {

              right = max_clip_x;

              if (left > max_clip_x)

                 continue;

              }

           memset((UCHAR  *)dest_addr+(unsigned int)left,

                  color,(unsigned int)(right-left+1));

           } // end for

       } // end else x clipping needed

    } // end Draw_Top_Tri

This function draws a triangle with a flat bottom:

    void Draw_Bottom_Tri(int x1,int y1,

                         int x2,int y2,

                         int x3,int y3,

                         int color,

                         UCHAR *dest_buffer, int mempitch)

    {

    // this function draws a triangle that has a flat bottom

    float dx_right,    // the dx/dy ratio of the right edge of line

          dx_left,     // the dx/dy ratio of the left edge of line

          xs,xe,       // the starting and ending points of the edges

          height;      // the height of the triangle

    int temp_x,        // used during sorting as temps

        temp_y,

        right,         // used by clipping

        left;

    // destination address of next scanline

    UCHAR  *dest_addr;

    // test order of x1 and x2

    if (x3 < x2)

       {

       temp_x = x2;

       x2     = x3;

       x3     = temp_x;

       } // end if swap

    // compute delta’s

    height = y3-y1;

    dx_left  = (x2-x1)/height;

    dx_right = (x3-x1)/height;

    // set starting points

    xs = (float)x1;

    xe = (float)x1; // +(float)0.5;

    // perform y clipping

    if (y1<min_clip_y)

       {

       // compute new xs and ys

       xs = xs+dx_left*(float)(-y1+min_clip_y);

       xe = xe+dx_right*(float)(-y1+min_clip_y);

       // reset y1

       y1=min_clip_y;

       } // end if top is off screen

    if (y3>max_clip_y)

       y3=max_clip_y;

    // compute starting address in video memory

    dest_addr = dest_buffer+y1*mempitch;

    // test if x clipping is needed

    if (x1>=min_clip_x && x1<=max_clip_x &&

        x2>=min_clip_x && x2<=max_clip_x &&

        x3>=min_clip_x && x3<=max_clip_x)

        {

        // draw the triangle

        for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)

            {

            memset((UCHAR  *)dest_addr+(unsigned int)xs,

                    color,(unsigned int)(xe-xs+1));

            // adjust starting point and ending point

            xs+=dx_left;

            xe+=dx_right;

            } // end for

        } // end if no x clipping needed

    else

       {

       // clip x axis with slower version

       // draw the triangle

       for (temp_y=y1; temp_y<=y3; temp_y++,dest_addr+=mempitch)

           {

           // do x clip

           left  = (int)xs;

           right = (int)xe;

           // adjust starting point and ending point

           xs+=dx_left;

           xe+=dx_right;

           // clip line

           if (left < min_clip_x)

              {

              left = min_clip_x;

              if (right < min_clip_x)

                 continue;

              }

           if (right > max_clip_x)

              {

              right = max_clip_x;

              if (left > max_clip_x)

                 continue;

              }

           memset((UCHAR  *)dest_addr+(unsigned int)left,

                  color,(unsigned int)(right-left+1));

           } // end for

       } // end else x clipping needed

    } // end Draw_Bottom_Tri

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.