Sources PureBasic
Sources PureBasicConsultez toutes les sources
Nombre d'auteurs : 41, nombre de sources : 88, dernière mise à jour : 13 août 2011
Les procédures ci dessous permettent de maintenir un angle dans un intervalle :
- WrapAngleSigned(angle.f) maintient un angle en radian entre [-Pi,Pi]
- WrapAngleDegSigned(angle.f) maintient un angle en degré entre [-180,180]
- WrapAngleUnsigned(angle.f) maintient un angle en radian entre [0,2*Pi]
- WrapAngleDegUnsigned(angle.f) maintient un angle en degré entre [0,360]
Procedure
.f WrapAngleSigned(angle.f); <- wraps a value into [-Pi,Pi] fringe
!
fldpi
!
fadd st0,st0; <- now i have 2*pi into st0
!
fld dword[p.v_angle]
!
fprem1
!
fstp st1
ProcedureReturn
EndProcedure
Procedure
.f WrapAngleDegSigned(angle.f); <- wraps a value into [-180,180] fringe
!
fild dword[@f] ; <- now i have 360 into st0
!
fld dword[p.v_angle]
!
fprem1
!
fstp st1
ProcedureReturn
!
@@:dd 360
EndProcedure
Procedure
.f WrapAngleUnsigned(angle.f); <- wraps a value into [0,2*Pi) fringe
!
fldpi; <- now i have pi into st0
!
fadd st0,st0; <- now i have 2*pi into st0
!
fld dword[p.v_angle]; <- now i have angle in st0, 2*pi into st1
!
fprem; <- now i have the remainder of angle/(2*pi) division (i.e. angle%(2*pi)) in st0, 2*pi in st1
!
fadd st1,st0;<- now i have angle%(2*pi) in st0, 2*pi+angle%(2*pi) into st1
!
fldz;<- now i have 0 in st0, angle%(2*pi) in st1, 2*pi+angle%(2*pi) into st2
!
fcomip st1; <- compare st0 and st1, and pop the stack, which means i have now angle%(2*pi) in st0, 2*pi+remainder into st1
!
fcmovnbe st0,st1; <- transfer st1 to st0 if not below or equal.
!
fstp st1; <- store st0 in st1 and pops stack, which means i have now the result in st0
ProcedureReturn
; <- return the result with this last pop
EndProcedure
Procedure
.f WrapAngleDegUnsigned(angle.f); <- wraps a value into [0,360) fringe
!
fild dword[@f] ; <- now i have 360 into st0
!
fld dword[p.v_angle]
!
fprem
!
fadd st1,st0
!
fldz
!
fcomip st1
!
fcmovnbe st0,st1
!
fstp st1
ProcedureReturn
!
@@:dd 360
EndProcedure
;Exemples d'utilisation en degré:
angle.f=
45
angleadd.f=-
90
angle.f=
WrapAngleDegUnsigned(angle.f+
angleadd.f)
Debug
angle
;
angle.f=
45
angleadd.f=-
90
angle.f=
WrapAngleDegSigned(angle.f+
angleadd.f)
Debug
angle
;
;Exemples d'utilisation en radian:
angle.f=
#PI
/
4
.0
angleadd.f=-
#PI
/
2
.0
angle.f=
WrapAngleUnsigned(angle.f+
angleadd.f)
Debug
angle
;
angle.f=
#PI
/
4
.0
angleadd.f=-
#PI
/
2
.0
angle.f=
WrapAngleSigned(angle.f+
angleadd.f)
Debug
angle
Ce code permet de tester si une zone mémoire ne contient que des zéros pour par exemple détecter une collision.
La procédure est optimisée et renvoie #False si toutes les donnéees sont à zéro sinon #True.
; Thorium le 21/11/09
; PB 4.40
Procedure
NoneZero(*
DestBufStart, DestBufSize.i)
CompilerSelect #PB_Compiler_Processor
CompilerCase #PB_Processor_x86
!
push edi
!
push ebx
!
mov edi,[p.p_DestBufStart+
8
]
!
mov edx,[p.v_DestBufSize+
8
]
!
mov ecx,edx
!
mov ebx,ecx
!
shr edx,4
!and
ecx,15
!
shr ecx,2
!and
ebx,3
!
test edx,edx
!
je NoneZero_FirstEnd
!
pxor xmm1,xmm1
!
align 4
!
NoneZero_FirstStart:
!
movdqu xmm0,[edi]
!
pcmpeqb xmm0,xmm1
!
add edi,16
!
pmovmskb eax,xmm0
!
cmp eax,$0000FFFF
!
jne NoneZero_EndTrueSse
!
dec edx
!
jne NoneZero_FirstStart
!
emms
!
align 4
!
NoneZero_FirstEnd:
!
test ecx,ecx
!
je NoneZero_SecondEnd
!
align 4
!
NoneZero_SecondStart:
!
mov eax,[edi]
!
test eax,eax
!
jne NoneZero_EndTrue
!
add edi,4
!
dec ecx
!
jne NoneZero_SecondStart
!
align 4
!
NoneZero_SecondEnd:
!
test ebx,ebx
!
je NoneZero_ThirdEnd
!
align 4
!
NoneZero_ThirdStart:
!
mov al,[edi]
!
test al,al
!
jne NoneZero_EndTrue
!
inc edi
!
dec ebx
!
jne NoneZero_ThirdStart
!
align 4
!
NoneZero_ThirdEnd:
!
pop ebx
!
pop edi
ProcedureReturn
#False
!
NoneZero_EndTrue:
!
pop ebx
!
pop edi
ProcedureReturn
#True
!
NoneZero_EndTrueSse:
!
pop ebx
!
pop edi
!
emms
ProcedureReturn
#True
CompilerCase #PB_Processor_x64
!
push rdi
!
push rbx
!
mov rdi,[p.p_DestBufStart+
16
]
!
mov rdx,[p.v_DestBufSize+
16
]
!
mov rcx,rdx
!
mov rbx,rcx
!
shr rdx,4
!and
rcx,15
!
shr rcx,2
!and
rbx,3
!
test rdx,rdx
!
je NoneZero_FirstEnd
!
pxor xmm1,xmm1
!
align 8
!
NoneZero_FirstStart:
!
movdqu xmm0,[rdi]
!
pcmpeqb xmm0,xmm1
!
add rdi,16
!
pmovmskb eax,xmm0
!
cmp eax,$0000FFFF
!
jne NoneZero_EndTrueSse
!
dec rdx
!
jne NoneZero_FirstStart
!
emms
!
align 8
!
NoneZero_FirstEnd:
!
test rcx,rcx
!
je NoneZero_SecondEnd
!
align 8
!
NoneZero_SecondStart:
!
mov eax,[rdi]
!
test eax,eax
!
jne NoneZero_EndTrue
!
add rdi,4
!
dec rcx
!
jne NoneZero_SecondStart
!
align 8
!
NoneZero_SecondEnd:
!
test rbx,rbx
!
je NoneZero_ThirdEnd
!
align 8
!
NoneZero_ThirdStart:
!
mov al,[rdi]
!
test al,al
!
jne NoneZero_EndTrue
!
inc rdi
!
dec rbx
!
jne NoneZero_ThirdStart
!
align 8
!
NoneZero_ThirdEnd:
!
pop rbx
!
pop rdi
ProcedureReturn
#False
!
NoneZero_EndTrue:
!
pop rbx
!
pop rdi
ProcedureReturn
#True
!
NoneZero_EndTrueSse:
!
pop rbx
!
pop rdi
!
emms
ProcedureReturn
#True
CompilerEndSelect
EndProcedure
;- Test de la procédure
*
Buffer =
AllocateMemory(64000
) ; Buffer de 64000 octets
*
Ptr.Byte =
*
Buffer +
64000
-
1
; On se place sur le dernier octet
*
ptr\b =
5
; Modifie le dernier octet du *Buffer
Debug
NoneZero(*
Buffer, MemorySize(*
Buffer))
Atan2(y,x) est l'angle en radians entre la partie positive de l'axe des x d'un plan, et le point de ce plan aux coordonnées (x,y). (wikipédia)
Note : La commande Atan2() est ajoutée dans la bibliothèque Math depuis la version 4.50.
Procedure
.d ATan2(y.d,x.d)
!
fld qword[p.v_y]
!
fld qword[p.v_x]
!
fpatan
ProcedureReturn
EndProcedure
y.d =
70
x.d =
0
#RAD2DEG
=
180
.0
/
#PI
; Conversion Radians en degrés
Debug
ATan2(y, x) *
#RAD2DEG