News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Recent posts

#1
16 bit DOS Programming / Re: Line Drawing
Last post by NoCforMe - Today at 11:05:07 AM
Here's my line-drawing routine. Not necessarily suggesting you copy and use it (you could if you wanted to), but it does work, so it might tell you something.

It even fills in "sparse" lines (lines with gaps between pixels) to make them look smoother.

The structure passed in in BX contains the starting and ending coordinates.

$slopeFactor EQU 100

DrawLine LABEL NEAR
; Draws a line from (x0, y0) to (x1, y1)
;
; On entry,
; ES:BX--> $LineStruct structure

; Get rise, run:
MOV AX, ES:[BX.$$gl_x1]
SUB AX, ES:[BX.$$gl_x0]
MOV Xdistance, AX
MOV AX, ES:[BX.$$gl_y1]
SUB AX, ES:[BX.$$gl_y0]
MOV CX, AX

; Determine if slope positive or negative:
TEST AX, 8000h
JZ dl_pos
MOV AX, -1 ;Slope negative.
MOV NegFlag, 1
NEG CX
JMP SHORT drw2

dl_pos: MOV AX, 1
MOV NegFlag, 0
drw2: MOV DeltaYsign, AX
MOV AX, CX ;Get Ydistance back.

; Calculate slope (y1-y0/x1-x0):
MOV DX, $slopeFactor
IMUL DX
IDIV Xdistance
MOV DeltaY, AX ;This is amount (fractional) to add to Y each time.
; Draw line:
drw5: MOV Y_accum, 0
MOV CX, Xdistance

MOV AX, ES:[BX.$$gl_x0]
MOV CurrX, AX
MOV AX, ES:[BX.$$gl_y0]
MOV CurrY, AX

MOV AL, ES:[BX.$$gl_Color]
MOV CurrColor, AL
dl_loop:
CALL DrawPixel
MOV AX, CurrY
MOV LastY, AX
; Move 1 notch on x-axis, determine new y-position:
INC CurrX ;Next X increment.
MOV AX, DeltaY
ADD Y_accum, AX ;Add increment to accumulator.
MOV AX, Y_accum
XOR DX, DX
IDIV SlopeFactor
CMP NegFlag, 1
JNE drw20
SUB CurrY, AX
JMP SHORT drw22
drw20: ADD CurrY, AX

; Adjust accumulator:
drw22: IMUL SlopeFactor
SUB Y_accum, AX ;Take out whole-number part.

; Fill in "sparse" lines:
drw30: MOV AX, CurrY
SUB AX, LastY
JNC drw33
NEG AX
drw33:
CMP AX, 1
JBE drw40 ;If increment <= 1, no need to fill in.
MOV AX, LastY
ADD AX, DeltaYsign ;Add or subtract 1, depending on slope sign.
MOV LastY, AX
PUSH CurrY
MOV CurrY, AX
DEC CurrX ;Fill in behind where we are now.
CALL DrawPixel ;Fill in line.
POP CurrY
INC CurrX
JMP drw30

drw40: LOOP dl_loop
drw99: RET
#2
16 bit DOS Programming / Re: Line Drawing
Last post by NoCforMe - Today at 10:53:41 AM
Your question is a non-trivial one. I just revisited some of my old line-drawing code which I hadn't looked at in years.

I did use scaling like I explained above. Thing is, since you're dealing with fractional values here, you need to keep an accumulator going to draw a line. Otherwise, let's say the slope is 0.5, you're never going to get any change in Y if you just go pixel-by-pixel since the incremental delta-Y value is less than one, therefore zero in integer arithmetic.

The basic idea is you start at your starting point, let's call it (x0, y0). Since you want a solid line and not a dotted one like you drew, we'll set our delta-X at 1, meaning we'll always move 1 pixel to the right.

The problem then becomes one of determining what our Y-position is for each pixel (we know what our X-position is because it increases by 1 each step). That's a matter of using scaling as shown above and calculating each next Y-position.

I'll leave it as an exercise for you. I'd suggest getting out paper and pencil and drawing lines to figure it out. Works for me, anyhow.

Hopefully this makes sense to you.
#3
16 bit DOS Programming / Re: Line Drawing
Last post by NoCforMe - Today at 10:28:23 AM
You do end up with fractions. That's one of the problems you have to solve. (See below for one possible solution.)

I think you meant the delta-Y values are going to be smaller than the delta-X values, but that's only true if the slope is less than 1 (45°).

Fractions: since you aren't using floating-point (I'm assuming: you could, but that's another whole ball o'wax), here's a way to deal with fractions: scaling up and scaling down.

Let's say you have a line with a slope of 0.5 (0,0)--> (6,3).
Use a scaling factor of let's say 100. Using the slope formula above, multiply delta-Y (the change in Y) by 100, then divide by delta-X:

(3-0) * 100 / (6-0) = 50

So our "slope" (scaled) is 50.
To plot a point, use the formula above, use 50 as the slope, then divide the result by the scaling factor (100) to calculate the actual coordinates.

#4
16 bit DOS Programming / Re: Line Drawing
Last post by tda0626 - Today at 10:01:20 AM
Quote from: NoCforMe on Today at 08:32:10 AMRemember high-school algebra?

Given 2 points, (x1,y1) & (x2, y2):

m = y2 - y1 / x2 - x1

m is the slope.

I know that. Usually the Y values are going to be smaller than the x values so we end up with a fraction but thanks anyway. I will see if I can find something on the Internet that explains it better.

#5
16 bit DOS Programming / Re: Line Drawing
Last post by NoCforMe - Today at 08:32:10 AM
Remember high-school algebra?

Given 2 points, (x1,y1) & (x2, y2):

m = y2 - y1 / x2 - x1

m is the slope.
#6
16 bit DOS Programming / Re: Line Drawing
Last post by tda0626 - Today at 08:20:51 AM
Quote from: NoCforMe on Today at 06:57:57 AMHint: at least two ways to do that:
2. Check the value of y each time through the loop to see if it's at the bottom of the screen.


Thanks, I got it to work. I was overthinking it for some reason when it was simple. I also added checks for the other screen borders.

How would I implement a slope? I want to eventually input start and end coordinates.

#7
The Orphanage / Re: Nugget finds a Turtle
Last post by sudoku - Today at 07:33:47 AM
Quote from: NoCforMe on Today at 07:29:05 AMStupid dog. Patient turtle.
:eusa_naughty:
Nah, she's still learning and definitely not stupid. Its the first time she had seen a snapping turtle up close. She sees them all the time around the edge of our pond, and chases them off and back into the pond.
#8
The Orphanage / Re: Nugget finds a Turtle
Last post by NoCforMe - Today at 07:29:05 AM
Stupid dog. Patient turtle.
#9
16 bit DOS Programming / Re: Line Drawing
Last post by NoCforMe - Today at 06:57:57 AM
Your "slope" isn't really the slope of the line (your actual slope is negative), but let's not worry about that for the moment: it's really the offset to the next y-position down for the next drawn pixel.

Your problem is not that the "slope" is increasing (it's not, it stays constant at 3) but that you're hitting the bottom line and wrapping around in the video buffer. So if you want to stop drawing at the bottom of the screen, then check to see if your y-position is at or past the bottom line, then exit your loop. (I'll leave it up to you to figure out how to determine that.)

Hint: at least two ways to do that:
1. Set your loop counter to a value that you know will only draw pixels to the bottom of the screen and stop.
2. Check the value of y each time through the loop to see if it's at the bottom of the screen.
#10
16 bit DOS Programming / Re: Line Drawing
Last post by sudoku - Today at 06:28:37 AM
Once you have clearly defined boundaries, you must tell the program what to do once a boundary is met.
Change direction, stop, start at a new x,y position, etc.
I don't know how to do it in 16 bit and as you have coded it, but it shouldn't be very difficult to implement.
You should be able to draw the lines as if it were a bouncing ping ping ball (staying within the boundaries), is that what you had in mind? (Where the lines appear to be bouncing off the 'walls'?).

After looking at the code again...
        dec cx
        jmp DrawLine
that jump should be jnz maybe, rather than jmp???
Then you wouldnt need the
cmp cx, 0
je EndLine
further up in the code.