Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Assembleur - Le bon octant pour le tracé de droites
(Article écrit par Jean-Sébastien Valette et extrait d'Amiga News Tech - novembre 1991)
|
|
Lorsque l'on veut tracer des droites au Blitter, la recherche de l'octant dans lequel se trouve
la droite est souvent problématique, surtout lorsque les points définissant la droite sont calculés.
On peut toujours utiliser la routine de Frédéric Mazué, parue dans l'ANT
de juillet 1990, mais je vous propose d'étudier la façon dont est conçu le code de l'octant pour mettre
au point une autre routine un peu plus rapide : on n'a plus à piocher dans une table, ce qui réclame beaucoup
de cycles de bus (l'instruction move.w d(pc),an en réclame 24 avec un 68000 !).
La composition du code de l'octant apparaît comme étant assez compliquée, mais en fait elle
est régie suivant une loi simple.
Soient (x1,y1) et (x2,y2) les coordonnées des points définissant la droite. Posons
DX=|X1-X2| et DY=|Y1-Y2| et étudions le tableau suivant.
L'analyse des deux premières lignes nous montre que si DX est supérieur à DY, alors le
troisième bit du code de l'octant est positionné. La ligne 3 semble nous montrer que le
second bit correspond à X1 par rapport à X2, mais la ligne 4 met toute cette jolie théorie
par terre. Par contre, ces deux lignes confirment l'hypothèse faite sur le troisième bit.
Les quatre dernières lignes nous montrent que cette hypothèse est valable.
Nous codons donc pour l'instant l'octant sous la forme Dxx, où D est positionné selon
DX et DY. Ce qui nous amène à séparer le précédent tableau en deux (c'est un très bon moyen
pour y voir clair).
Et que voit-on ? Tout simplement que l'octant peut être codé sous la forme 1AB ou 0BA !
Et comment le voit-on ? Très simple. Pour A d'abord. Dans le tableau de gauche, on constate
que sur les deux premières lignes le premier bit est à 0 alors qu'il est mis pour les lignes
3 et 4, ce qui correspondrait à A=1 si Y1>Y2 et A=0 si Y1X2 et B=0 si X1
Avec un peu de recul, on décide plus généralement que le code de l'octant est de la
forme XYZ avec X=F(DX,DY), Y=G(Pdelta) et Z=H(Gdelta), où Pdelta et Gdelta sont respectivement le plus
petit et le plus grand de DX et DY.
Enfin, voici un extrait de source mettant tout ceci en application. On peut le mettre à la
place de la routine "Recherche_octant" du programme de l'ANT n°14.
Note : la routine "Recherche_octant" que je vous propose a été modifiée pour être
compatible avec le programme de Frédéric Mazué. Les changements sont indiqués en commentaire avec les
anciennes valeurs.
;
;
; tracer de droite au Blitter, programme de l'ANT 14
; la routine recherche_octant a ete modifiée
;
;
;
; **exec.library**
OldOpenLibrary equ -408
CloseLibrary equ -414
AlloocMem equ -198
FreeMem equ -210
SuperState equ -150
UserState equ -156
; **graphics lybrary**
OwnBlitter equ -456
DisownBlitter equ -462
; **intuition library**
OpenScreen equ -198
CloseScreen equ -66
; **CHIPS**
BLTSIZE equ $58
BLTCPTH equ $48
BLTBPTH equ $4C
BLTAPTH equ $50
BLTDPTH equ $54
BLTCMOD equ $60
BLTBMOD equ $62
BLTAMOD equ $64
BLTDMOD equ $66
BLTCON0 equ $40
BLTCON1 equ $42
BLTAFWM equ $44
BLTALWM equ $46
BLTDDAT equ $00
BLTCDAT equ $70
BLTBDAT equ $72
BLTADAT equ $74
DMACON equ $96
DMACONR equ $02
Debut
Move.l $4,A6
Lea graf_name,A1
Jsr OldOpenLibrary(A6)
Move.l D0,graf_base
Lea int_name,A1
Jsr OldOpenLibrary(A6)
Move.l D0,int_base
Move.l int_base,A6
Lea ecran,A0
Jsr OpenScreen(A6)
Move.l D0,canal_ecran
lea $dff000,A5
Bsr Blitter_Busy
Move.l graf_base,A6
Jsr OwnBlitter(A6)
Bsr Recherche_octant
Bsr adresse_depart
Move.l D0,BLTCPTH(A5)
Move.l D0,BLTDPTH(A5)
Move.w #40,BLTCMOD(A5)
Move.w #40,BLTDMOD(A5)
Clr.l D0
Clr.l D1
Clr.l D2
Clr.l D6
Clr.l D7
Move.w PDelta,D0
Move.w GDelta,D1
Muls #4,D0
Move.w D0,BLTBMOD(A5)
Move.w D0,D2
Muls #2,D1
Sub.w D1,D0
Roxl.w #7,D7
Move.l D0,BLTAPTH(A5)
Move.w D2,D0
Muls #2,D1
Sub.w D1,D0
Move.w D0,BLTAMOD(A5)
Move.w #$8000,BLTADAT(A5)
Move.w #$ffff,BLTBDAT(A5)
Move.w #$ffff,BLTAFWM(A5)
Move.w #$ffff,BLTALWM(A5)
Move.w X1,D0
And.w #$000f,D0
Ror.w #4,D0
Or.w D0,D6
Or.w D0,D7
Or.w #$0bca,D6
Move.w D6,BLTCON0(A5)
Move.b octant,D0
Ext.w D0
; Rol.w #2,D0
Bset #0,D0
Or.w D0,D7
; Bset #1,D7
Move.w D7,BLTCON1(A5)
Move.w GDelta,D0
add.w #$01,D0
Muls #64,D0
Add.w #00002,D0
Move.w D0,BLTSIZE(A5)
Bsr Blitter_Busy
Jsr DisownBlitter(A6)
souris
Lea $bfe001,A5
Btst #6,(A5)
Bne.s souris
Move.l int_base,A6
Move.l canal_ecran,A0
Jsr CloseScreen(A6)
Move.l $04,A6
Move.l int_base,A1
Jsr CloseLibrary(A6)
Move.l graf_base,A1
Jsr CloseLibrary(A6)
Rts
Blitter_Busy
Btst #14,DMACONR(A5)
Bne.s Blitter_Busy
Rts
Recherche_octant ;trouve l'octant et le renvoie dans D0
Move.w X1,D0 ;D3 contient PDeltat et D2 GDelta
Move.w Y1,D1 ;D0 à D3 sont modifies
Move.w X2,D2
Move.w Y2,D3
Sub.w D1,D3
Bpl.s Y1_inf_Y2 ;si Y1 est plus petit
Neg.w D3 ;DY>0
Moveq #4,D1 ;A=1 (cf article),si l'on veut eviter le decalage
Bra.s Test_X ;lors de la preparation de BLTCON1 mettre 4 dans D1
Y1_inf_Y2
Moveq #0,D1 ;si Y1 |
|