Solved

DirectX Line Drawing

Posted on 1998-08-20
6
577 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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 50 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
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!

 
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

630 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