Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

DirectX Line Drawing

Posted on 1998-08-20
6
Medium Priority
?
584 Views
Last Modified: 2008-02-01
I am using MSVC++5.0, DirectX 5.0, full-screen mode, and an 800x600x16 resolution.

I have a routine to draw a line using DirectDraw.  This routine works, only it doesn't draw the line exactly where I want it to.  It draws the line approximately at 1/2 the x position specified and it won't do colors correcly, the only color that I know of that doesn't generate a compiler warning is 0 (black).

Here is the code for the routine:

BOOL DirectDrawWin::Line(LPDIRECTDRAWSURFACE surf, int x1, int y1, int x2, int y2, BYTE color)
{
      // Bresenham's algorithm (IBM 1965)

      int dx, dy;
      int x_inc, y_inc;
      int error = 0;
      int index;

      HRESULT r;

      DDSURFACEDESC desc;
      ZeroMemory(&desc, sizeof(desc));
      desc.dwSize = sizeof(desc);
      desc.dwFlags=DDSD_WIDTH | DDSD_HEIGHT;
      if(surf->GetSurfaceDesc(&desc)!=DD_OK)
            return FALSE;
      int w=desc.dwWidth;
      int h=desc.dwHeight;

      r = surf->Lock(0, &desc, DDLOCK_WAIT  | DDLOCK_WRITEONLY, 0);
      if (r != DD_OK)
            return FALSE;

      BYTE* surfbits = (BYTE*)desc.lpSurface;
      BYTE* pixel = surfbits + y1 * desc.lPitch + x1;

      dx = x2 - x1;
      dy = y2 - y1;

      // Determine slope
      if(dx >= 0)
      {
            x_inc = 1;
      }
      else
      {
            x_inc = -1;
            dx = -dx;
      }

      if(dy >= 0)
      {
            y_inc = desc.lPitch;
      }
      else
      {
            y_inc = -desc.lPitch;
            dy = -dy;
      }

      // Draw the line based upon deltas
      if(dx > dy)
      {
            for(index=0;index<dx;index++)
            {
                  // Set the pixel
                  *pixel = color;

                  // Discriminate
                  error += dy;

                  // Test for overflow
                  if(error > dx)
                  {
                        error -= dx;
                        pixel += y_inc;
                  }

                  // Move to the next pixel
                  pixel += x_inc;
            }
      }
      else
      {
            for(index=0;index<=dy;index++)
            {
                  // Set the pixel
                  *pixel = color;

                  // Discriminate
                  error += dx;

                  // Test for overflow
                  if(error > 0)
                  {
                        error -= dy;
                        pixel += x_inc;
                  }

                  // Move to the next pixel
                  pixel += y_inc;
            }
      }

      surf->Unlock(0);

      return TRUE;
}

This is simply Bresenham's algorithm, so anyone familiar with line drawing should recognize it.  I think my problem lies with using BYTE pointers when they should be WORD pointers, but switch to WORD pointers generates errors.
0
Comment
Question by:Egore
  • 3
  • 3
6 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1170815
If you have 16 colors, then there are two pixels stored in each byte, but your algorithm treats it as if there is one pixles stored in each byte.  Your algoritm needds work, or you need to use it in 256  color mode.
0
 
LVL 3

Author Comment

by:Egore
ID: 1170816
I realize this, do you know how to change the algorithm to make it work with 16bit color?  That's my main problem...
0
 
LVL 22

Accepted Solution

by:
nietod earned 150 total points
ID: 1170817
Its very painful.  I think I would take the following tact.  I would peform the calculations in terms of a nible offset into the screen memory.  That is, I would not add on "desc.lpSurface" at the start (you will have to add it on each time you access memory, not at the start of the calculations.)  In this case, the pointer you will calculate (before lpsurface is added on) is twice the size it should be. This is because it expresses a distance in nibbles (half a byte) not bytes.  You wil then bet a pointer to the byte to change by dividing this pointer (offset, really) by 2 and then adding on the lpsuface.  Now the important thing is you don't want to change the whole byte pointed to by this pointer.  Only one nibble.  Which one?  Well of the first pointer (offset) is odd, the low nibble, if it is even, then the high one.

Make sense?  let me know if you have questions.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 3

Author Comment

by:Egore
ID: 1170818
I'm sorry if I was unclear, but I am dealing with **16 bit** color, not 16 colors.  That means that each color is represented by two bytes.  A WORD variable is two bytes, but it gives me an error if 'surfbits' and 'pixel' are WORD size.

Sorry about the confusion.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1170819
That is a lot easier.  I would just convert to WORD * pointers instead of BYTE * pointers.   It looks like everything else should stay the same except that you need to use 1/2 of lPitch everywhere where you currently use lPitch.  In this case lPitch must be even, so you know that LPitch/2 will by accurate.
0
 
LVL 3

Author Comment

by:Egore
ID: 1170820
This worked, changing everything to WORD pointers.  The problem that I had is that, before posting this question, I tried changing everything to DWORD pointers, and that did not work.

Thanks for the help...

(By the way, the code is the same except for the WORD pointers...)
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

971 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question