This proc takes the horizontal and vertical delta values of two points and returns the angle between them in tenths of degrees (range 0-3600). I just converted some C example I found on the web (didn't mention the original author). Maybe someone finds it useful.


; Converts horizontal and vertical delta values into
; tenths of degrees (range 0-3600).
; Converted from C example by unkown author.
DeltaToAngle proc deltaX:DWORD, deltaY:DWORD
LOCAL temp:DWORD
.data
dta_rangeval_000 REAL4 1800.0
.code
mov ecx, deltaX
mov edx, deltaY

or edx, edx
jnz @dta1
mov eax, 900
cmp ecx, 0
jg @F
mov eax, 2700
@@:
ret
@dta1:
xor eax, eax
or ecx, ecx
jnz @dta2
cmp edx, eax
jg @F
mov eax, 1800
@@:
ret
ret
@dta2:

finit

fild deltaY
fild deltaX

fpatan ;ST(0)=angle in radians
fldpi ;ST(1)=angle in radians, ST(0)=pi
fdivp ST(1),ST(0) ;ST(0)=angle/pi
fmul dta_rangeval_000 ;ST(0)=(angle/pi) * 1800 = angle in degrees (*10)
fistp temp ;temp=ST(0)=angle in degrees (*10)

mov eax, 900
sub eax, temp

@@:
cmp eax, 0
jge @F
add eax, 3600
jmp @B
@@:

@@:
cmp eax, 3600
jle @F
sub eax, 3600
jmp @B
@@:
ret
DeltaToAngle endp


Thomas

P.S. The coordinates and angles are defined as follows:
Posted on 2002-01-02 10:32:50 by Thomas
hiiii few ideas for optimaztion




DeltaToAngle proc deltaX:DWORD, deltaY:DWORD
LOCAL temp:DWORD
.data
dta_rangeval_000 REAL4 1800.0
.code
mov ecx, deltaX
mov edx, deltaY

or edx, edx
jnz @dta1
mov eax, 900
cmp ecx, 1
sbb edx,edx ;carry should be set if ecx<1
;edx is allready a zero but leave it edx,edx and not edx,0 for size optimaztion
and edx,2700-900 ;if ecx<1 add 1800 else add 0
add eax,edx

; jg @F
; mov eax, 2700
@@:
ret
@dta1:

or ecx, ecx
jnz @dta2
cmp edx, 1 ; if edx>=eax nocarry
sbb eax,eax ;eax=0 or -1 we dont need xor here

and eax,1800 ; if carry =1 eax=-1 and eax=1800
; jg @F
; mov eax, 1800
@@:
ret
ret ; why twice?

@dta2:
xor eax, eax ; xor here
finit

fild deltaY
fild deltaX

fpatan ;ST(0)=angle in radians
fldpi ;ST(1)=angle in radians, ST(0)=pi
fdivp ST(1),ST(0) ;ST(0)=angle/pi
fmul dta_rangeval_000 ;ST(0)=(angle/pi) * 1800 = angle in degrees (*10)
fistp temp ;temp=ST(0)=angle in degrees (*10)

mov eax, 900
sub eax, temp

sub eax,3600
@@:
add eax,3600
cmp eax, 0
jl @B ;jc @B


; jge @F
; add eax, 3600
; jmp @B
@@:

add eax,3600 ; 1 cycle more instead 5( i think)
@@:
sub eax, 3600 ; sub set the carry too ;
; actully the same as cmp just it keeps the vaule of the sub
; cmp eax, 3600
jg @B

; cmp eax, 3600
; jle @F
; sub eax, 3600
; jmp @B
@@:

ret
DeltaToAngle endp


i think the code works . have check it ( dont have time its getting late here and i have school tomorrow :grin: )

anyway let me know what you think , maybe there are more things to change. . but like i mantion before dont have time now .. ( few ideas has been based on a tip from the greatest anger help )

bye

eko

EDIT : fix something in the algo
Posted on 2002-01-02 16:43:49 by eko
Thanks for the optimizations, I don't call the proc very often so optimizations are not essential but it's always nice to have..
The division by pi and the multiplication by 1800 could be wrapped up into one multiplication (*1800/pi), saves a few clocks.

Thomas
Posted on 2002-01-03 16:22:24 by Thomas
Thomas, shouldn't that 3600 be 2700 in the diagram?
And the range should be 0-3599 because 3600=0?
Posted on 2002-01-03 23:13:35 by bitRAKE
BitRake: yeah you're totally right on both things... I really had to mess with the code to get it working so I was tired when I posted it here..

Thomas
:stupid:
Posted on 2002-01-04 04:31:23 by Thomas