home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
No Fragments Archive 10: Diskmags
/
nf_archive_10.iso
/
MAGS
/
FALKMAG
/
FKM_07_2.ZIP
/
CLIPPING.S
/
CP_2DL_S.S
next >
Wrap
Text File
|
1997-04-23
|
12KB
|
555 lines
* routine de clipping de segment de droite
* algorithme de fenêtrage 2D explicite
* par Golio Junior pour Falk'mag 7
* Définition de l'image
Video_mode equ %000100100 * 40 col, 200 lig, 65536 cou, TV Pal
Taille_ecran equ 320*200*2
ecran_largeur equ 320
ecran_hauteur equ 200
Pas_Fond equ 0
* zone de clipping
min_x equ 100
max_x equ 220
min_y equ 40
max_y equ 160
include "principa.s"
prg_init
* effacement de l'écran
move.w #ecran_largeur*ecran_hauteur/8-1,d0
move.l #-1,d1
movea.l adr_ecran,a0
prg_init_b1
move.l d1,(a0)+
move.l d1,(a0)+
move.l d1,(a0)+
move.l d1,(a0)+
dbra d0,prg_init_b1
* coloriage de la zone de clipping pour bien voir
movea.l adr_ecran,a0
adda.l #(ecran_largeur*min_y+min_x)*2,a0
move.l #0,d2
move.w #max_y-min_y-1,d0
prg_init_b2
move.w #(max_x-min_x)/8-1,d1
prg_init_b3
move.l d2,(a0)+
move.l d2,(a0)+
move.l d2,(a0)+
move.l d2,(a0)+
dbra d1,prg_init_b3
adda.l #(ecran_largeur-(max_x-min_x))*2,a0
dbra d0,prg_init_b2
clr.w compteur
rts
prg
* prise au hasard des coordonnées du segment
move.w #17,-(sp)
trap #14
addq.l #2,sp
move.w d0,d4
andi.w #$1FF,d4 * il faut quand même que les coordonnées
* ne soient pas trop exotiques!
move.w #17,-(sp)
trap #14
addq.l #2,sp
move.w d0,d5
andi.w #$1FF,d5
move.w #160,d6 * les autres coordonnées pour voir quelquechose
move.w #100,d7
* début du clipping simple
* comparaison avec le bord gauche de la fenêtre
* pour savoir si les extrémités sont à l'intérieur
cmp.w #min_x,d4
bgt clip_gauche_bis
* le bord gauche est coupé par le 1er point
cmp.w #min_x,d6
blt pas_visible
* mais par un seul point
* calcul du point d'intersection
* calcul de la pente
move.w d6,d0
sub.w d4,d0 * résultat positif car d6>d4 !
move.w d7,d1
sub.w d5,d1
beq clip_gauche_horizontal * segment horizontal
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dx
sub.w #min_x,d4
neg.w d4
ext.l d4
* calcul du dy à ajouter
muls.l d4,d1
swap d1
add.w d1,d5
clip_gauche_horizontal * segment horizontal,
* donc intersection facile à calculer
move.w #min_x,d4
bra clip_droit
clip_gauche_bis
cmp.w #min_x,d6
bgt clip_droit
* le bord gauche est coupé par le second point,
* mais pas par le premier
* calcul du point d'intersection
* calcul de la pente
move.w d4,d0
sub.w d6,d0 * résultat positif car d4>d6 !
move.w d5,d1
sub.w d7,d1
beq clip_gauche_bis_horizontal * segment horizontal
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dx
sub.w #min_x,d6
neg.w d6
ext.l d6
* calcul du dy à ajouter
muls.l d6,d1
swap d1
add.w d1,d7
clip_gauche_bis_horizontal * segment horizontal,
* donc intersection facile à calculer
move.w #min_x,d6
clip_droit
* comparaison avec le bord droit de la fenêtre
* pour savoir si les extrémités sont à l'intérieur
cmp.w #max_x,d4
blt clip_droit_bis
* le bord droit est coupé par le 1er point
cmp.w #max_x,d6
bgt pas_visible
* mais par un seul point
* calcul du point d'intersection
* calcul de la pente
move.w d4,d0
sub.w d6,d0 * résultat positif car d4>d6 !
move.w d7,d1
sub.w d5,d1
beq clip_droit_horizontal * segment horizontal
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dx
sub.w #max_x,d4
ext.l d4
* calcul du dy à ajouter
muls.l d4,d1
swap d1
add.w d1,d5
clip_droit_horizontal * segment horizontal,
* donc intersection facile à calculer
move.w #max_x,d4
bra clip_haut
clip_droit_bis
cmp.w #max_x,d6
blt clip_haut
* le bord droit est coupé par le second point,
* mais pas par le premier
* calcul du point d'intersection
* calcul de la pente
move.w d6,d0
sub.w d4,d0 * résultat positif car d6>d4 !
move.w d5,d1
sub.w d7,d1
beq clip_droit_bis_horizontal * segment horizontal
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dx
sub.w #max_x,d6
ext.l d6
* calcul du dy à ajouter
muls.l d6,d1
swap d1
add.w d1,d7
clip_droit_bis_horizontal * segment horizontal,
* donc intersection facile à calculer
move.w #max_x,d6
clip_haut
* comparaison avec le bord haut de la fenêtre
* pour savoir si les extrémités sont à l'intérieur
cmp.w #min_y,d5
bgt clip_haut_bis
* le bord gauche est coupé par le 1er point
cmp.w #min_y,d7
blt pas_visible
* mais par un seul point
* calcul du point d'intersection
* calcul de la pente
move.w d7,d0
sub.w d5,d0 * résultat positif car d7>d5 !
move.w d6,d1
sub.w d4,d1
beq clip_haut_vertical * segment vertical
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dy
sub.w #min_y,d5
neg.w d5
ext.l d5
* calcul du dx à ajouter
muls.l d5,d1
swap d1
add.w d1,d4
clip_haut_vertical * segment vertical,
* donc intersection facile à calculer
move.w #min_y,d5
bra clip_bas
clip_haut_bis
cmp.w #min_y,d7
bgt clip_bas
* le bord haut est coupé par le second point,
* mais pas par le premier
* calcul du point d'intersection
* calcul de la pente
move.w d5,d0
sub.w d7,d0 * résultat positif car d4>d6 !
move.w d4,d1
sub.w d6,d1
beq clip_haut_bis_vertical * segment vertical
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dy
sub.w #min_y,d7
neg.w d7
ext.l d7
* calcul du dx à ajouter
muls.l d7,d1
swap d1
add.w d1,d6
clip_haut_bis_vertical * segment vertical,
* donc intersection facile à calculer
move.w #min_y,d7
clip_bas
* comparaison avec le bord bas de la fenêtre
* pour savoir si les extrémités sont à l'intérieur
cmp.w #max_y,d5
blt clip_bas_bis
* le bord bas est coupé par le 1er point
cmp.w #max_y,d7
bgt pas_visible
* mais par un seul point
* calcul du point d'intersection
* calcul de la pente
move.w d5,d0
sub.w d7,d0 * résultat positif car d5>d7 !
move.w d6,d1
sub.w d4,d1
beq clip_bas_vertical * segment vertical
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dy
sub.w #max_y,d5
ext.l d5
* calcul du dx à ajouter
muls.l d5,d1
swap d1
add.w d1,d4
clip_bas_vertical * segment vertical,
* donc intersection facile à calculer
move.w #max_y,d5
bra clip_fin
clip_bas_bis
cmp.w #max_y,d7
blt clip_fin
* le bord bas est coupé par le second point,
* mais pas par le premier
* calcul du point d'intersection
* calcul de la pente
move.w d7,d0
sub.w d5,d0 * résultat positif car d7>d5 !
move.w d4,d1
sub.w d6,d1
beq clip_bas_bis_vertical * segment vertical
swap d1
clr.w d1
ext.l d0
divs.l d0,d1
* calcul de dy
sub.w #max_y,d7
ext.l d7
* calcul du dx à ajouter
muls.l d7,d1
swap d1
add.w d1,d6
clip_bas_bis_vertical * segment vertical,
* donc intersection facile à calculer
move.w #max_y,d7
clip_fin
move.w d4,d0
move.w d5,d1
move.w d6,d2
move.w d7,d3
move.l #$F0F0F0F0,d4
bsr ligne
pas_visible
rts
* routine de ligne en 65536 couleurs
* recoit en D0 : X, D1 : Y : de départ
* D2 : X, D3 : Y : d'arrivée
* D4 : couleur sur 32 bits !!
* modifie D0-D7, A0
ligne
move.l #ecran_largeur*2,d7 * stockage de yinc
move.w d2,d5 * calcul de dx dans D5
sub.w d0,d5
beq rout5
bpl xpasneg1 * si dx est nul, ligne verticale !!
* si dx negatif, donc d2<d0
* donc le premier point devient d2,d3
neg.w d5
exg.l d2,d0
exg.l d3,d1
xpasneg1
* on trace toujours vers les x croissants
* calcul de dy
move.w d3,d6
sub.w d1,d6
beq rout4
* dy est nul, ligne horizontal
bpl ypasneg1
* dy négatif, donc d4<d1
neg.w d6
* tracé en montant vers la droite
* donc d7=-ecran_largeur*2
neg.l d7
ypasneg1
cmp.w d5,d6
* comparaison dx et dy
bmi rout2 * <0
beq rout3 * =0 : une diagonale !!!
* à la fin : d5 : dx
* d6 : dy
* routine 1
* ici dx>0, dy>0 et dy>dx
* a pus besoin de d2, d3, et dx après division
rout1
* si dx = 1 : 2 pixels de large !!
* donc il faut rajouter 1 à chaque d
addq.w #1,d5
addq.w #1,d6
* décalage de 16 bits pour la division
swap d5
clr.w d5
divu.w d6,d5
* division de dx par dy + division par 16 bits
* d5 contient la pente : résultat sur 16 bits
* boucle sur d6
subq.w #1,d6
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
* somme = 0
moveq.l #0,d3
* rappels des valeur des regsitres a ce point :
* d0 :
* d1 :
* d2 :
* d3 : somme
* d4 : couleur
* d5 : pente
* d6 : delta y
* d7 : offset pour changement de ligne
ligneb1
add.w d5,d3
bcs lignenx1
* pas de déplacement suivant x
move.w d4,(a0)
adda.l d7,a0
dbra d6,ligneb1
rts
lignenx1
move.w d4,(a0)+
adda.l d7,a0
dbra d6,ligneb1
rts
* routine 2
* ici dx>0, dy>0 et dy<dx
* a pus besoin de d2, d3, et dy après division
rout2
* correction de d
addq.w #1,d5
addq.w #1,d6
* décalage de 16 bits
swap d6
clr.w d6
divu.w d5,d6
* division de dy par dx + division par 16 bits
* d6 contient la pente : résultat sur 16 bits
* boucle sur d5
subq.w #1,d5
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
* somme = 0
moveq.l #0,d3
* d0 :
* d1 :
* d2 :
* d3 : somme
* d4 : couleur
* d5 : delta x
* d6 : pente
* d7 : offset pour changement de ligne et de pixel
ligneb2
move.w d4,(a0)+
add.w d6,d3
bcc ligneny2
* pas de déplacement suivant y
adda.l d7,a0
ligneny2
dbra d5,ligneb2
rts
* ici dx>0, dy>0 et dx=dy
* une diagonale!!
rout3
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
* division par 2 de d5
lsr.w #1,d5
bcc ligneb3
* si retenue alors nombre impair
move.w d4,(a0)+
adda.l d7,a0
* ce qui permet d'afficher 2 points par 2 points
ligneb3
move.w d4,(a0)+
adda.l d7,a0
move.w d4,(a0)+
adda.l d7,a0
dbra d5,ligneb3
rts
* ici dy est nul
* et dx positif
* ligne horizontale
rout4
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
* division de d5 par 2
lsr.w #1,d5
bcc ligneb4
* d5 : nombre impaire
move.w d4,(a0)+
ligneb4
move.l d4,(a0)+ * 2 pixels d'un coup !
dbra d5,ligneb4
rts
* ici dx est nul
* et dy est inconnu
* ligne verticale
rout5
move.w d3,d6
sub.w d1,d6
bmi rout5_yneg
beq rout6
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
* division par 2 de d6
lsr.w #1,d6
bcc ligneb5
* d6 : nombre impaire
move.w d4,(a0)
adda.l d7,a0
ligneb5
move.w d4,(a0)
adda.l d7,a0
move.w d4,(a0)
adda.l d7,a0
dbra d6,ligneb5
rts
rout5_yneg
neg.w d6
neg.l d7
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
* division par deux de d6
lsr.w #1,d6
bcc ligneb5_yneg
* d6 : nombre impair
move.w d4,(a0)
adda.l d7,a1
ligneb5_yneg
move.w d4,(a0)
adda.l d7,a0
move.w d4,(a0)
adda.l d7,a0
dbra d6,ligneb5_yneg
rts
* deltax est nul
* deltay est nul
* c'est un point
* OK
rout6
* calcul d'adresse du 1er point dans a0
movea.l adr_ecran,a0
add.w d0,d0
adda.w d0,a0
mulu.w #ecran_largeur*2,d1
adda.l d1,a0
move.w d4,(a0)
rts
include "principh.s"
section BSS
compteur ds.w 1