Author Topic: Bezier curves HELP!!  (Read 9235 times)

0 Members and 1 Guest are viewing this topic.

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Bezier curves HELP!!
« on: March 20, 2011, 11:19:52 pm »
Hi, I'm quite  new to ASM, so I probably made a bunch of mistakes.

I'm trying to write a program that draws a Bezier curve based on given control points. However......it doesn't seem to be working. I think it's an issue with my math for calculating the next iteration of control points, but I've looked it over again and again and I can't figure out what's wrong.  :banghead:

Here's the code, complete with a surplus of comments (probably more than I really need, but I just wanted to show my though processes).

//EDIT: Here's an explanation for constructing Bezier curves. Hopefully it'll help :)
http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Constructing_B.C3.A9zier_curves


Code: [Select]
.nolist
#include "ti83plus.inc"
#define    ProgStart    $9D95
.list
.org    $9D95 - 2
    .db    t2ByteTok, tAsmCmp

b_call(_GrBufClr) ;clear stuff...
b_call(_ClrLCDFull)

ld a, 255
ld (_time), a ;set _time to 255 (when used in calculation it ends up acting as a lower part of a fixed point number)
ld a, (_len) ;_len is always 4 right now. That'll change once I get this thing working.
ld (_level), a
call LoadVals ;load the _initx and _inity values into _px and _py
_tloop:
call Bezier ;calculate and plot the point on the curve at _time
call LoadVals ;reload the _initx/y values
ld hl, _time
dec (hl) ;dec _time
xor a
cp (hl)
jr nz, _tloop ;loop until _time is zero

call Plot ;plot the first point (shouldn't be necessary, but just in case)

ld hl, _px ;load points at _px+(_len) and _py+(_len) into _px and _py
ld bc, (_len)
dec bc ;_len is the total length, so subtract one to get the last one
add hl, bc ;set hl to address of _px+(_len)
ld de, _px
ldi

inc bc ;ldi decrements bc, so add 1 to restore it
add hl, bc
ld de, _py
ldi

call Plot
b_call(_GrBufCpy)
ret


LoadVals:
ld hl, _initx
ld de, _px
ld bc, 8
ldir
ret


Bezier:
ld a, 0
ld (_n), a ;reset _n
ld hl, _level
dec (hl) ;go to next (or first) level iteration

ld a, (hl)
cp 0
jr nz, bez

call Plot ;if the level is zero, draw the point at _px,_py to the graph buffer
b_call(_GrBufCpy) ;display for testing purposes
jr bez_ret ;end the routine

bez:
ld hl, (_n) ;for each point p[_n] where _n=0 to _n=_level-1
ld h, 0 ;_n is one byte, so zero out h
push hl ;save _n
ld de, _px ;we want to calculate the _nth byte starting at _px
;Div_pt has add hl,de in it.
call Div_pt
ld (hl), a ;save the new x coordinate to _px[_n]

pop hl ;restore _n
ld de, _py ;now we want the _nth byte starting at _py
call Div_pt
ld (hl), a ;save the new y coordinate to _py[_n]

ld hl, _n
ld a, (_level)
inc (hl) ;_n=_n+1
cp (hl)
jr nc, bez ;loop until _n>=_level-1

call Bezier ;call Bezier again to calculate the next level iteration

bez_ret:
ld hl, _level
inc (hl) ;reset _level to the previous level iteration before returning
ret


Div_pt:
;input
; de = start address of point array
; hl = value at _n
;output
; a = p[_n]+(p[_n+1]-p[_n])*(_time/256)
; hl = address of p[_n]
;note that p[ ] is either _px[ ] or _py[ ] depending on input de value

add hl, de ;find the address of the desired byte
push hl
pop de
inc de ;de = hl+1
ld a, (de)
sub (hl) ;subtract p[_n] (at hl) from p[_n+1] (at de)
;a is now the difference of the two points

push hl ;save location of p[_n]
ld e, 0
jr nc, _pskip
ld e, 1 ;if (de)-(hl) is negative, e is 1
neg ;make a positive
_pskip:
;##################################################################
;##################################################################

;This is the part that I guess isn't working

;Basically, I'm using _time as a percentage (where 256 is 100%)
;The point at _time percent of the line between p[_n] and p[_n+1] is calculated here
;    and stored in a (later stored in p[_n] back in the main Bezier routine)

;I'm calculating this:
;   p[_n]+(p[_n+1]-p[_n])*(_time/256)

ld h, a ;make hl fixed point with value a
ld l, 0
ld a, (_time)
ld d, a ;multiply by _time
push de ;save e, which holds the sign
call HL_Times_D
;because HL is 2 bytes and D is one byte, this SHOULD be the same
;  as multiplying by d as if it was the decimal part of a fixed point number

pop de ;restore e
ld a, e
cp 0 ;check for negative
ld a, h ;in case of negative, get the value to invert
jr z, _nskip
neg ;if a was negative before, make it negative again
_nskip:
pop hl
add a,(hl) ;add the original p[_n] value
ret
;##################################################################
;##################################################################

Plot:
ld a, (_py) ;get the y coordinate into l
ld l, a
or a
ret m ;ret if negative
cp 64
ret nc ;ret if y>=64
ld a, (_px) ;get x
or a
ret m ;ret if negative
cp 96
ret nc ;ret if x>=96
call GetPixel ;turn on pixel (x,y)
or (hl)
ld (hl), a
ret


GetPixel: ;this came from the "Learn TI-83/84+ ASM in 28 days" or whatever guide
;a = x coordinate
;l = y coordinate
ld h, 0
ld d, h
ld e, l
add hl, hl
add hl, de
add hl, hl
add hl, hl
ld e, a
srl e
srl e
srl e
add hl, de
ld de, PlotSScreen
add hl, de
and 7
ld b,a
ld a, $80
ret z
__gloop:
rrca
djnz __gloop
ret


HL_Times_D: ;this came from the "Learn TI-83/84+ ASM in 28 days" or whatever guide
;in the guide it was DE_Times_A, but I was already using HL and D for division
;  so I thought it was a good idea to just keep those values
ld a, d
ld de, 0
ex de, hl
ld b, 8
__mloop:
rrca
jr nc, __mskip
add hl, de
__mskip:
sla e
rl d
djnz __mloop
ret


Div_HL_D: ;this came from the "Learn TI-83/84+ ASM in 28 days" or whatever guide
xor a
ld b, 16
__dloop:
add hl, hl
rla
jr c, __overflow
cp d
jr c, __dskip
__overflow:
sub d
inc l
__dskip:
djnz __dloop
ret


_time:
.db 0
_level:
.db 0 ;control point iteration level
_n:
.db 0 ;control point to calculate at any given time
_len:
.dw 4 ;number of control points for the curve
_initx:
.db 4, 7, 13, 20 ;control point x values
_inity:
.db 6, 23, 19, 2 ;control point y values
_px:
.db 0, 0, 0, 0 ;x values for calculations
_py:
.db 0, 0, 0, 0 ;y values for calculations
.end
.end

If anyone could help me out that would be wonderful!

Thanks!
-Zippy Dee
« Last Edit: March 20, 2011, 11:25:42 pm by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...


Offline ztrumpet

  • The Rarely Active One
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5712
  • Rating: +364/-4
  • If you see this, send me a PM. Just for fun.
    • View Profile
Re: Bezier curves HELP!!
« Reply #1 on: March 21, 2011, 05:19:37 pm »
I doubt if this will help, but Michael_Lee made a routine to do this in Axe: http://ourl.ca/4129/186296

Sadly, I don't understand Asm well and can't help you, but hopefully someone else will stumble over this thread who can help.  Good luck! :)
« Last Edit: March 21, 2011, 07:39:02 pm by ztrumpet »

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: Bezier curves HELP!!
« Reply #2 on: March 21, 2011, 05:27:17 pm »
Maybe it would help by instead of going pixel by pixel, do what Michale_Lee did and just calculate 8 or so points on the curve and connect them with straight lines.  Unfortunately I too can only provide conceptual help, as I am not an asm expert either D:

Offline Michael_Lee

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1019
  • Rating: +124/-9
    • View Profile
Re: Bezier curves HELP!!
« Reply #3 on: March 21, 2011, 07:37:50 pm »
Blasphemy!  People spelled my name incorrectly, twice!

I don't know any asm at all, so I'm of even less help, but I can point you to a webpage I found which provided the algorithm I adapted: http://freespace.virgin.net/hugo.elias/graphics/x_bezier.htm
My website: Currently boring.

Projects:
Axe Interpreter
   > Core: Done
   > Memory: Need write code to add constants.
   > Graphics: Rewritten.  Needs to integrate sprites with constants.
   > IO: GetKey done.  Need to add mostly homescreen IO stuff.
Croquette:
   > Stomping bugs
   > Internet version: On hold until I can make my website less boring/broken.

Offline ztrumpet

  • The Rarely Active One
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5712
  • Rating: +364/-4
  • If you see this, send me a PM. Just for fun.
    • View Profile
Re: Bezier curves HELP!!
« Reply #4 on: March 21, 2011, 07:40:06 pm »
Blasphemy!  People spelled my name incorrectly, twice!
I'm very sorry.  :-X  This is why I should check things like this before posting.  <_<

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: Bezier curves HELP!!
« Reply #5 on: March 21, 2011, 07:42:07 pm »
I spelt it wrong because I was copying it from ztrumpet :P

* Hides *

Offline Michael_Lee

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1019
  • Rating: +124/-9
    • View Profile
Re: Bezier curves HELP!!
« Reply #6 on: March 21, 2011, 07:44:07 pm »
It's fine - don't worry about it.
I just like to say the word 'blasphamy'. :)

...

Blasphamy!
My website: Currently boring.

Projects:
Axe Interpreter
   > Core: Done
   > Memory: Need write code to add constants.
   > Graphics: Rewritten.  Needs to integrate sprites with constants.
   > IO: GetKey done.  Need to add mostly homescreen IO stuff.
Croquette:
   > Stomping bugs
   > Internet version: On hold until I can make my website less boring/broken.

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Bezier curves HELP!!
« Reply #7 on: March 21, 2011, 09:38:59 pm »
First off, I love how this is structured, nested loops are so cool and clever. But it's amazing that such a small mistake can cause the entire program to fail.

You had:
Code: [Select]
ld h, a
ld l, 0

You wanted:
Code: [Select]
ld h, 0
ld l, a

Down in your problem area. By putting time in l, then reading it from h, you are essentially dividing it by 256. I attached a file with some edits I made to it, it works fine with just that little change, but these are just some things to help you. For instance, I think it just looks better to render from left to right, but that might just be me.

The lines don't come out that pretty because you are getting some serious rounding issues (11 rounds per pixel), so I would suggest making all of your number .256 decimal, but of course that requires a complete rewrite. I'll see if I can give you an example so you can see what it would look like.

And lastly, you can get some serious speed improvements by using a custom GrBufCpy, or even better yet, only plot the current byte in the LCD driver, but that's a bit advanced.
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Bezier curves HELP!!
« Reply #8 on: March 22, 2011, 08:53:54 pm »
I was bored, so here is that demo I talked about. It uses 256 point decimal, which is great for physics applications.

It is also commented for clarity.
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Bezier curves HELP!!
« Reply #9 on: March 24, 2011, 01:20:45 am »
I swear I tried that. I tried putting time in H and L and I tried both multiplying and dividing (which is why I had both Div_HL_D and HL_Times_D there). Oh well, thank you so much! And thanks for all the comments and for that other example (which is obviously 10,000,000,000 times better than mine, and way over my head)!

Can you explain what you mean about making all the numbers .256 decimal? You mean like fixed-point numbers? I was going to try to make it fixed-point, but all the scaling that's involved for the multiplication confused me, so I gave up. I also was going to try to make it write to the LCD, but I figured it's probably best to get one that just WORKS before trying to get too fancy (Well, what an ASM noob like me considers fancy).

Thanks for all your help! I'm really trying to learn to navigate ASM, and this alone has been very enlightening. It's always the small things that get you. :P
There's something about Tuesday...


Pushpins 'n' stuff...


Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Bezier curves HELP!!
« Reply #10 on: March 24, 2011, 07:11:30 am »
I don't know any asm at all, so I'm of even less help, but I can point you to a webpage I found which provided the algorithm I adapted: http://freespace.virgin.net/hugo.elias/graphics/x_bezier.htm
Thanks! That's actually a fairly good explanation on that page. That's only for cubic beziers though, isn't it? Though you don't often need more than a cubic bezier...

Also, now that you've done a bezier routine in axe (which looks fantastic and is very speed-efficient), you should write a b-spline routine :D

Edit: oops, sorry for the double post :\
« Last Edit: March 24, 2011, 07:11:57 am by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...


Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Bezier curves HELP!!
« Reply #11 on: March 25, 2011, 05:13:17 pm »
Sorry for the over your head stuff, lately I've been tending to write pretty cryptic code for optimizations. Like using a loop to do x then y, but that's just easier for me I guess.

When I say .256 decimal, I mean fixed point decimal, but in a very specific way. First you take your typical 1 byte value, and place it in the high byte of a two byte number. The lower byte of that two byte is now its decimal place. So just treat it like a two byte number, and when the time comes to see what the value is, only read the upper byte.

As for updating the LCD, that example right there is a clean as it gets (I love DWAIT.) Just make sure that you grab the byte from the buffer, or else you will overwrite the old bits with white.
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Bezier curves HELP!!
« Reply #12 on: March 25, 2011, 05:36:59 pm »
Isn't the LCD done with columns x rows instead of rows x columns though? I thought I saw that somewhere...
There's something about Tuesday...


Pushpins 'n' stuff...


Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Bezier curves HELP!!
« Reply #13 on: March 25, 2011, 10:51:44 pm »
Well, that's technically a yes. But in all reality, it doesn't matter at all. The only time it matters is when you are sending commands 4-7 which set the way the driver moves after each write (up, down, left, right). But at least on wikiTI it says both the x/y and the vertical/horizontal, so you don't have to worry about it.

Also, it's pretty easy to remember that the columns start at $20 and the rows start at $80. Those are the two numbers you'll need if you write a graphBufferCopy routine.
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Bezier curves HELP!!
« Reply #14 on: March 26, 2011, 05:01:07 am »
Also, it's pretty easy to remember that the columns start at $20 and the rows start at $80.
What do you mean by that?
There's something about Tuesday...


Pushpins 'n' stuff...