Welcome
Welcome to a320

You are currently viewing our boards as a guest, which gives you limited access to view most discussions and access our other features. By joining our free community, you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content, and access many other special features. Registration is fast, simple, and absolutely free, so please, join our community today!

How to draw lines?

Any and all A320 homebrew topics

Moderator: Moderators

How to draw lines?

Postby cdesign30 on Mon May 11, 2009 12:15 pm

How to draw lines? I know how to draw filled rectangles, triangles and circles using m_pDraw2D->FillRect, m_pDraw2D->FillTriangle, and m_pDraw2D->FillCircle, but not lines. I don't found any docs about this. Any help is welcome.

Thanks, Doug
cdesign30
 
Posts: 23
Joined: Sun Apr 26, 2009 8:04 pm

Re: How to draw lines?

Postby Firefox on Mon May 11, 2009 8:04 pm

A quick way to do it would be to call the triangle-drawing function with two of the vertices set to the coordinates of one end of the line and the third vertex set to the coordinates of the other end.
Firefox
 
Posts: 3
Joined: Sat Mar 21, 2009 1:56 pm

Re: How to draw lines?

Postby Wop on Fri May 15, 2009 11:02 am

Hi

I didnt found a function to draw lines so i created one based on some examples on the net:

Code: Select all
void GameEngine::DrawLine(int x1,int y1,int x2,int y2,int32 color) {
    int deltax,deltay,x,y,xinc1,xinc2,yinc1,yinc2,  den,num,numadd,numpixels,curpixel ;
    deltax = abs(x2 - x1);        // The difference between the x's
    deltay = abs(y2 - y1);        // The difference between the y's
    x = x1;                       // Start x off at the first pixel
    y = y1;                       // Start y off at the first pixel

    if (x2 >= x1) {                // The x-values are increasing
        xinc1 = 1;
        xinc2 = 1;
    }
    else {                         // The x-values are decreasing
        xinc1 = -1;
        xinc2 = -1;
    }

    if (y2 >= y1) {                 // The y-values are increasing
        yinc1 = 1;
        yinc2 = 1;
    }
    else {                         // The y-values are decreasing
        yinc1 = -1;
        yinc2 = -1;
    }

    if (deltax >= deltay) {        // There is at least one x-value for every y-value
        xinc1 = 0;                  // Don't change the x when numerator >= denominator
        yinc2 = 0;                  // Don't change the y for every iteration
        den = deltax;
        num = deltax / 2;
        numadd = deltay;
        numpixels = deltax;         // There are more x-values than y-values
    }
    else  {                        // There is at least one y-value for every x-value
        xinc2 = 0;                  // Don't change the x for every iteration
        yinc1 = 0;                  // Don't change the y when numerator >= denominator
        den = deltay;
        num = deltay / 2;
        numadd = deltax;
        numpixels = deltay;         // There are more y-values than x-values
    }

    for (curpixel = 0; curpixel <= numpixels; curpixel++) {
        PutPixel(x, y,color);             // Draw the current pixel
        num += numadd;              // Increase the numerator by the top of the fraction
        if (num >= den) {            // Check if numerator >= denominator
            num -= den;               // Calculate the new numerator value
            x += xinc1;               // Change the x as appropriate
            y += yinc1;               // Change the y as appropriate
        }
        x += xinc2;                 // Change the x as appropriate
        y += yinc2;                 // Change the y as appropriate
    }

}


The PutPixel() function is from the WonderSwan emulator by JorgeHJ http://blog.tipesoft.com/

Code: Select all
void GameEngine::PutPixel(int x, int y, UINT16 color) {
    r = (color & red_mask) >> 10;
    g = (color & green_mask) >> 5;
    b = (color & blue_mask);

    // Expand to 8-bit values:
    UINT16 red   = r << 3;
    UINT16 green = g << 3;
    UINT16 blue  = b << 3;

    Pixel color1(red,green,blue);
    s32 ofs = (x*A320_SCREEN_WIDTH) + (y);

    ptr[ofs] = color1;
}



and where ptr is defined in the constructor as:

Code: Select all
   //Init pointer to VRAM
   ptr = m_pDraw2D->GetVRAMPtr();


I use this code to draw rotating 3d polygons as mini dingoo programming samples and works great.

I hope this may help you.

Regards
Wop
 
Posts: 2
Joined: Thu Mar 05, 2009 9:17 pm

Re: How to draw lines?

Postby SiENcE on Fri May 15, 2009 11:59 am

The Putpixel function is non standard. You better use this. It's also faster.

Code: Select all
/// pre-render proccess
void GameEngine::PutPixel(int x, int y, u8 r,u8 g, u8 b )
{
   Pixel* ptr = m_pDraw2D->GetVRAMPtr();
   Pixel color1(r,g,b);
   s32 ofs = (y*A320_SCREEN_WIDTH) + (x);
   ptr[ofs] = color1;
}


To draw a screen use:

Code: Select all
   //Pixel by pixel
   int r = 0;
   int g = 255;
   int b = 0;
   for(int y = 0; y < A320_SCREEN_HEIGHT;y++)
   {
      for (int x=0; x < A320_SCREEN_WIDTH; x++)
      {
         PutPixel(x,y,r,g,b);
      }
      r += 1;
      g -= 1;
      b += 1;
   }
SiENcE
 
Posts: 67
Joined: Wed Apr 29, 2009 9:19 am
Location: Berlin/Germany

Re: How to draw lines?

Postby cdesign30 on Sun May 17, 2009 3:59 pm

Hi, all. Thanks to Firefox, Wop, and Science for code and tips. I did a web search and found a fast and efficient algorithm to draw straight lines. So I adapted the code for the GameEngine and created three new functions:

Line(X1, Y1, X2, Y2, R, G, B) -> draw a line from (x1,y1) to (x2,y2) with RGB color
MoveTo(ORIG_X, ORIG_Y) -> move the 'LineTo' function start point to (ORIG_X, ORIG_Y)
LineTo(X, Y, R, G, B) -> Draw a line from last point to (X, Y) with RGB color


Line function use "PutPixel" function.

Functions in Public Functions (GameEngine.h):

Code: Select all
void Line(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b);
void MoveTo(int x, int y);
void LineTo(int x, int y, u8 r, u8 g, u8 b);


Variables declaration in begin of GameEngine.cpp code:

Code: Select all
//Start point to LineTo
int ORIG_X = 160;
int ORIG_Y = 120;


The 3 functions code in GameEngine:

Code: Select all
// SIGNAL function:
int sgn (long a) {
  if (a > 0) return +1;
  else if (a < 0) return -1;
  else return 0;
}

//Line Function
void GameEngine::Line(int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b)
{
  long u,s,v,d1x,d1y,d2x,d2y,n;
  int m;
  int  i;
  u   = x2-x1;
  v   = y2-y1;
  d1x = sgn(u);
  d1y = sgn(v);
  d2x = sgn(u);
  d2y = 0;
  m   = abs(u);
  n   = abs(v);
  if (m<=n) {
    d2x = 0;
    d2y = sgn(v);
    m   = abs(v);
    n   = abs(u);
  }
  s = (int)(m / 2);
  for (i=0;i< (int)(m);i++) {
    PutPixel(x1,y1,r,g,b);
    s += n;
    if (s >= m) {
      s -= m;
      x1 += d1x;
      y1 += d1y;
    }
    else {
      x1 += d2x;
      y1 += d2y;
    }
  }
}

//MoveTo function
void GameEngine::MoveTo(int x, int y)
{
   ORIG_X = x;
   ORIG_Y = y;
}

//LineTo function
void GameEngine::LineTo(int x, int y, u8 r, u8 g, u8 b)
{
   Line(ORIG_X, ORIG_Y, x, y, r, g, b);
   ORIG_X = x;
   ORIG_Y = y;
}


Usage examples in GameEngine::Render :

Code: Select all
   m_pDraw2D->Clear(40,40,40); // clear screen
   Line(10,20,300,180,0,0,255);//Draw a blue line
   Line(100,0,120,200,0,255,0); // Draw a green line
   Line(310,0,0,240,255,255,255); //Draw a white line
   MoveTo(37,63); // Move start point to (37,63)
   LineTo(128,230,255,255,0);//Draw a yellow line from start point to (128,230)

   LineTo(280,0,255,255,0);//Draw a yellow line from last point to (280,0)


I did some tests with line animations and these functions are FAST!

Cheers, Doug
cdesign30
 
Posts: 23
Joined: Sun Apr 26, 2009 8:04 pm

Re: How to draw lines?

Postby flatmush on Sun May 17, 2009 4:21 pm

Having if statements and function calls with a loop body is very bad on mips, since it doesn't have inline conditionals, you're better having two loops.
Check out my minesweeper source code for a more optimal version of bresenhams, however it's still not optimal, I need to remove the multiply in the loop body by using pointer arithmetic.
C99 samples without using s2dsdk | MineSweeper | AstroLander
For help with dingoo programming or just in general, join our IRC at irc://irc.freenode.net/#dingoo-a320
flatmush
 
Posts: 30
Joined: Thu May 14, 2009 1:29 pm
Location: Manchester, UK

Re: How to draw lines?

Postby cdesign30 on Sun May 17, 2009 9:34 pm

Thanks for tips, flatmush. I have seen the research you have done and I will exemine the source code of minesweeper to improve my code.

Cheers, Doug
cdesign30
 
Posts: 23
Joined: Sun Apr 26, 2009 8:04 pm

Re: How to draw lines?

Postby flatmush on Tue May 19, 2009 10:29 pm

If you want to see some very complex, but highly optimized code then look at the line drawing algorithms in the Astro Lander that I just released.
It uses clipping and various other optimization tricks to draw lines and triangles in a very optimized way, I hope to expand it into a full fixed point graphics library.
C99 samples without using s2dsdk | MineSweeper | AstroLander
For help with dingoo programming or just in general, join our IRC at irc://irc.freenode.net/#dingoo-a320
flatmush
 
Posts: 30
Joined: Thu May 14, 2009 1:29 pm
Location: Manchester, UK

Re: How to draw lines?

Postby cdesign30 on Tue May 19, 2009 10:37 pm

Hi, flatmush.

I downloaded the source code and I'm examining just now. Very interessant! Thanks.

Cheers, doug
cdesign30
 
Posts: 23
Joined: Sun Apr 26, 2009 8:04 pm

Re: How to draw lines?

Postby cdesign30 on Tue May 19, 2009 10:52 pm

Wow! Your code is very similar to what I developed (not the above code, but another). One loop per drawn line without "if" statement in between. But your code seems better.

Cheers, Doug
cdesign30
 
Posts: 23
Joined: Sun Apr 26, 2009 8:04 pm

Next

Return to Homebrew

Who is online

Users browsing this forum: nine10 and 2 guests