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 >
Text File  |  1997-04-23  |  12KB  |  555 lines

  1. * routine de clipping de segment de droite
  2. * algorithme de fenêtrage 2D explicite
  3. * par Golio Junior pour Falk'mag 7
  4.  
  5. * Définition de l'image
  6. Video_mode        equ %000100100    * 40 col, 200 lig, 65536 cou, TV Pal
  7. Taille_ecran    equ 320*200*2
  8. ecran_largeur    equ 320
  9. ecran_hauteur    equ 200
  10. Pas_Fond        equ 0
  11.  
  12. * zone de clipping
  13. min_x    equ 100
  14. max_x    equ 220
  15. min_y    equ 40
  16. max_y    equ 160
  17.  
  18.     include "principa.s"
  19.  
  20. prg_init
  21.                 * effacement de l'écran
  22.     move.w #ecran_largeur*ecran_hauteur/8-1,d0
  23.     move.l #-1,d1
  24.     movea.l adr_ecran,a0
  25. prg_init_b1
  26.     move.l d1,(a0)+
  27.     move.l d1,(a0)+
  28.     move.l d1,(a0)+
  29.     move.l d1,(a0)+
  30.     dbra d0,prg_init_b1
  31.                 * coloriage de la zone de clipping pour bien voir 
  32.     movea.l adr_ecran,a0
  33.     adda.l #(ecran_largeur*min_y+min_x)*2,a0
  34.     move.l #0,d2
  35.     move.w #max_y-min_y-1,d0
  36. prg_init_b2
  37.     move.w #(max_x-min_x)/8-1,d1
  38. prg_init_b3
  39.     move.l d2,(a0)+
  40.     move.l d2,(a0)+
  41.     move.l d2,(a0)+
  42.     move.l d2,(a0)+
  43.     dbra d1,prg_init_b3
  44.     adda.l #(ecran_largeur-(max_x-min_x))*2,a0
  45.     dbra d0,prg_init_b2
  46.     
  47.     clr.w compteur
  48.     rts
  49.  
  50. prg
  51.                 * prise au hasard des coordonnées du segment
  52.     move.w #17,-(sp)
  53.     trap #14
  54.     addq.l #2,sp
  55.     move.w d0,d4
  56.     andi.w #$1FF,d4        * il faut quand même que les coordonnées
  57.                 * ne soient pas trop exotiques!
  58.     
  59.     move.w #17,-(sp)
  60.     trap #14
  61.     addq.l #2,sp
  62.     move.w d0,d5
  63.     andi.w #$1FF,d5
  64.  
  65.     move.w #160,d6        * les autres coordonnées pour voir quelquechose
  66.     move.w #100,d7
  67.  
  68.                 * début du clipping simple
  69.                 * comparaison avec le bord gauche de la fenêtre
  70.                 * pour savoir si les extrémités sont à l'intérieur
  71.     cmp.w #min_x,d4
  72.     bgt clip_gauche_bis
  73.                 * le bord gauche est coupé par le 1er point
  74.     cmp.w #min_x,d6
  75.     blt pas_visible
  76.                 * mais par un seul point
  77.                 * calcul du point d'intersection
  78.                 * calcul de la pente
  79.     move.w d6,d0
  80.     sub.w d4,d0        * résultat positif car d6>d4 !
  81.     move.w d7,d1
  82.     sub.w d5,d1
  83.     beq clip_gauche_horizontal    * segment horizontal
  84.     swap d1
  85.     clr.w d1
  86.     ext.l d0
  87.     divs.l d0,d1
  88.                 * calcul de dx
  89.     sub.w #min_x,d4
  90.     neg.w d4
  91.     ext.l d4
  92.                 * calcul du dy à ajouter
  93.     muls.l d4,d1
  94.     swap d1
  95.     add.w d1,d5
  96.  
  97. clip_gauche_horizontal        * segment horizontal,
  98.                 * donc intersection facile à calculer
  99.     move.w #min_x,d4
  100.     bra clip_droit
  101. clip_gauche_bis
  102.     cmp.w #min_x,d6
  103.     bgt clip_droit
  104.                 * le bord gauche est coupé par le second point,
  105.                 * mais pas par le premier
  106.                 * calcul du point d'intersection
  107.                 * calcul de la pente
  108.     move.w d4,d0
  109.     sub.w d6,d0        * résultat positif car d4>d6 !
  110.     move.w d5,d1
  111.     sub.w d7,d1
  112.     beq clip_gauche_bis_horizontal    * segment horizontal
  113.     swap d1
  114.     clr.w d1
  115.     ext.l d0
  116.     divs.l d0,d1
  117.                 * calcul de dx
  118.     sub.w #min_x,d6
  119.     neg.w d6
  120.     ext.l d6
  121.                 * calcul du dy à ajouter
  122.     muls.l d6,d1
  123.     swap d1
  124.     add.w d1,d7
  125.  
  126. clip_gauche_bis_horizontal        * segment horizontal,
  127.                 * donc intersection facile à calculer
  128.     move.w #min_x,d6
  129. clip_droit
  130.                 * comparaison avec le bord droit de la fenêtre
  131.                 * pour savoir si les extrémités sont à l'intérieur
  132.     cmp.w #max_x,d4
  133.     blt clip_droit_bis
  134.                 * le bord droit est coupé par le 1er point
  135.     cmp.w #max_x,d6
  136.     bgt pas_visible
  137.                 * mais par un seul point
  138.                 * calcul du point d'intersection
  139.                 * calcul de la pente
  140.     move.w d4,d0
  141.     sub.w d6,d0        * résultat positif car d4>d6 !
  142.     move.w d7,d1
  143.     sub.w d5,d1
  144.     beq clip_droit_horizontal    * segment horizontal
  145.     swap d1
  146.     clr.w d1
  147.     ext.l d0
  148.     divs.l d0,d1
  149.                 * calcul de dx
  150.     sub.w #max_x,d4
  151.     ext.l d4
  152.                 * calcul du dy à ajouter
  153.     muls.l d4,d1
  154.     swap d1
  155.     add.w d1,d5
  156.  
  157. clip_droit_horizontal            * segment horizontal,
  158.                 * donc intersection facile à calculer
  159.     move.w #max_x,d4
  160.     bra clip_haut
  161. clip_droit_bis
  162.     cmp.w #max_x,d6
  163.     blt clip_haut
  164.                 * le bord droit est coupé par le second point,
  165.                 * mais pas par le premier
  166.                 * calcul du point d'intersection
  167.                 * calcul de la pente
  168.     move.w d6,d0
  169.     sub.w d4,d0        * résultat positif car d6>d4 !
  170.     move.w d5,d1
  171.     sub.w d7,d1
  172.     beq clip_droit_bis_horizontal    * segment horizontal
  173.     swap d1
  174.     clr.w d1
  175.     ext.l d0
  176.     divs.l d0,d1
  177.                 * calcul de dx
  178.     sub.w #max_x,d6
  179.     ext.l d6
  180.                 * calcul du dy à ajouter
  181.     muls.l d6,d1
  182.     swap d1
  183.     add.w d1,d7
  184.  
  185. clip_droit_bis_horizontal        * segment horizontal,
  186.                 * donc intersection facile à calculer
  187.     move.w #max_x,d6
  188. clip_haut
  189.                 * comparaison avec le bord haut de la fenêtre
  190.                 * pour savoir si les extrémités sont à l'intérieur
  191.     cmp.w #min_y,d5
  192.     bgt clip_haut_bis
  193.                 * le bord gauche est coupé par le 1er point
  194.     cmp.w #min_y,d7
  195.     blt pas_visible
  196.                 * mais par un seul point
  197.                 * calcul du point d'intersection
  198.                 * calcul de la pente
  199.     move.w d7,d0
  200.     sub.w d5,d0        * résultat positif car d7>d5 !
  201.     move.w d6,d1
  202.     sub.w d4,d1
  203.     beq clip_haut_vertical    * segment vertical
  204.     swap d1
  205.     clr.w d1
  206.     ext.l d0
  207.     divs.l d0,d1
  208.                 * calcul de dy
  209.     sub.w #min_y,d5
  210.     neg.w d5
  211.     ext.l d5
  212.                 * calcul du dx à ajouter
  213.     muls.l d5,d1
  214.     swap d1
  215.     add.w d1,d4
  216.  
  217. clip_haut_vertical            * segment vertical,
  218.                 * donc intersection facile à calculer
  219.     move.w #min_y,d5
  220.     bra clip_bas
  221. clip_haut_bis
  222.     cmp.w #min_y,d7
  223.     bgt clip_bas
  224.                 * le bord haut est coupé par le second point,
  225.                 * mais pas par le premier
  226.                 * calcul du point d'intersection
  227.                 * calcul de la pente
  228.     move.w d5,d0
  229.     sub.w d7,d0        * résultat positif car d4>d6 !
  230.     move.w d4,d1
  231.     sub.w d6,d1
  232.     beq clip_haut_bis_vertical    * segment vertical
  233.     swap d1
  234.     clr.w d1
  235.     ext.l d0
  236.     divs.l d0,d1
  237.                 * calcul de dy
  238.     sub.w #min_y,d7
  239.     neg.w d7
  240.     ext.l d7
  241.                 * calcul du dx à ajouter
  242.     muls.l d7,d1
  243.     swap d1
  244.     add.w d1,d6
  245.  
  246. clip_haut_bis_vertical        * segment vertical,
  247.                 * donc intersection facile à calculer
  248.     move.w #min_y,d7
  249. clip_bas
  250.                 * comparaison avec le bord bas de la fenêtre
  251.                 * pour savoir si les extrémités sont à l'intérieur
  252.     cmp.w #max_y,d5
  253.     blt clip_bas_bis
  254.                 * le bord bas est coupé par le 1er point
  255.     cmp.w #max_y,d7
  256.     bgt pas_visible
  257.                 * mais par un seul point
  258.                 * calcul du point d'intersection
  259.                 * calcul de la pente
  260.     move.w d5,d0
  261.     sub.w d7,d0        * résultat positif car d5>d7 !
  262.     move.w d6,d1
  263.     sub.w d4,d1
  264.     beq clip_bas_vertical        * segment vertical
  265.     swap d1
  266.     clr.w d1
  267.     ext.l d0
  268.     divs.l d0,d1
  269.                 * calcul de dy
  270.     sub.w #max_y,d5
  271.     ext.l d5
  272.                 * calcul du dx à ajouter
  273.     muls.l d5,d1
  274.     swap d1
  275.     add.w d1,d4
  276.  
  277. clip_bas_vertical            * segment vertical,
  278.                 * donc intersection facile à calculer
  279.     move.w #max_y,d5
  280.     bra clip_fin
  281. clip_bas_bis
  282.     cmp.w #max_y,d7
  283.     blt clip_fin
  284.                 * le bord bas est coupé par le second point,
  285.                 * mais pas par le premier
  286.                 * calcul du point d'intersection
  287.                 * calcul de la pente
  288.     move.w d7,d0
  289.     sub.w d5,d0        * résultat positif car d7>d5 !
  290.     move.w d4,d1
  291.     sub.w d6,d1
  292.     beq clip_bas_bis_vertical    * segment vertical
  293.     swap d1
  294.     clr.w d1
  295.     ext.l d0
  296.     divs.l d0,d1
  297.                 * calcul de dy
  298.     sub.w #max_y,d7
  299.     ext.l d7
  300.                 * calcul du dx à ajouter
  301.     muls.l d7,d1
  302.     swap d1
  303.     add.w d1,d6
  304.  
  305. clip_bas_bis_vertical            * segment vertical,
  306.                 * donc intersection facile à calculer
  307.     move.w #max_y,d7
  308. clip_fin
  309.     move.w d4,d0
  310.     move.w d5,d1
  311.     move.w d6,d2
  312.     move.w d7,d3
  313.     move.l #$F0F0F0F0,d4
  314.     bsr ligne
  315. pas_visible
  316.     rts
  317.  
  318. * routine de ligne en 65536 couleurs
  319. * recoit en D0 : X, D1 : Y : de départ
  320. *           D2 : X, D3 : Y : d'arrivée
  321. * D4 : couleur sur 32 bits !!
  322. * modifie D0-D7, A0
  323. ligne
  324.     move.l #ecran_largeur*2,d7    * stockage de yinc
  325.     move.w d2,d5        * calcul de dx dans D5
  326.     sub.w d0,d5
  327.     beq rout5    
  328.     bpl xpasneg1        * si dx est nul, ligne verticale !!
  329.                 * si dx negatif, donc d2<d0
  330.                 * donc le premier point devient d2,d3
  331.     neg.w d5
  332.     exg.l d2,d0
  333.     exg.l d3,d1
  334. xpasneg1
  335.                 * on trace toujours vers les x croissants
  336.                 * calcul de dy
  337.     move.w d3,d6
  338.     sub.w d1,d6
  339.     beq rout4            
  340.                 * dy est nul, ligne horizontal    
  341.     bpl ypasneg1
  342.                 * dy négatif, donc d4<d1
  343.     neg.w d6
  344.                 * tracé en montant vers la droite
  345.                 * donc d7=-ecran_largeur*2
  346.     neg.l d7
  347. ypasneg1
  348.     cmp.w d5,d6
  349.                 * comparaison dx et dy
  350.     bmi rout2            * <0
  351.     beq rout3            * =0 : une diagonale !!!
  352.  
  353.                 * à la fin : d5 : dx
  354.                 *            d6 : dy
  355.     * routine 1
  356.     * ici dx>0, dy>0 et dy>dx
  357.     * a pus besoin de d2, d3, et dx après division
  358. rout1
  359.                 * si dx = 1 : 2 pixels de large !!
  360.                 * donc il faut rajouter 1 à chaque d
  361.     addq.w #1,d5
  362.     addq.w #1,d6
  363.                 * décalage de 16 bits pour la division
  364.     swap d5
  365.     clr.w d5
  366.     divu.w d6,d5        
  367.                 * division de dx par dy + division par 16 bits
  368.                 * d5 contient la pente : résultat sur 16 bits
  369.                 * boucle sur d6
  370.     subq.w #1,d6
  371.                 * calcul d'adresse du 1er point dans a0
  372.     movea.l adr_ecran,a0
  373.     add.w d0,d0
  374.     adda.w d0,a0
  375.     mulu.w #ecran_largeur*2,d1
  376.     adda.l d1,a0
  377.                 * somme = 0
  378.     moveq.l #0,d3    
  379.                 * rappels des valeur des regsitres a ce point : 
  380.                 * d0 : 
  381.                 * d1 : 
  382.                 * d2 : 
  383.                 * d3 : somme
  384.                 * d4 : couleur
  385.                 * d5 : pente
  386.                 * d6 : delta y
  387.                 * d7 : offset pour changement de ligne 
  388. ligneb1
  389.     add.w d5,d3
  390.     bcs lignenx1
  391.                 * pas de déplacement suivant x
  392.     move.w d4,(a0)
  393.     adda.l d7,a0
  394.     dbra d6,ligneb1
  395.     rts
  396. lignenx1
  397.     move.w d4,(a0)+
  398.     adda.l d7,a0
  399.     dbra d6,ligneb1
  400.     rts
  401.  
  402.     * routine 2
  403.     * ici dx>0, dy>0 et dy<dx
  404.     * a pus besoin de d2, d3, et dy après division
  405. rout2
  406.                 * correction de d
  407.     addq.w #1,d5
  408.     addq.w #1,d6
  409.                 * décalage de 16 bits
  410.     swap d6
  411.     clr.w d6
  412.     divu.w d5,d6
  413.                 * division de dy par dx + division par 16 bits
  414.                 * d6 contient la pente : résultat sur 16 bits
  415.                 * boucle sur d5
  416.     subq.w #1,d5
  417.                 * calcul d'adresse du 1er point dans a0
  418.     movea.l adr_ecran,a0
  419.     add.w d0,d0
  420.     adda.w d0,a0
  421.     mulu.w #ecran_largeur*2,d1
  422.     adda.l d1,a0
  423.                 * somme = 0
  424.     moveq.l #0,d3
  425.                 * d0 : 
  426.                 * d1 : 
  427.                 * d2 : 
  428.                 * d3 : somme
  429.                 * d4 : couleur
  430.                 * d5 : delta x
  431.                 * d6 : pente
  432.                 * d7 : offset pour changement de ligne et de pixel
  433. ligneb2
  434.     move.w d4,(a0)+
  435.     add.w d6,d3
  436.     bcc ligneny2            
  437.                 * pas de déplacement suivant y 
  438.     adda.l d7,a0
  439. ligneny2
  440.     dbra d5,ligneb2
  441.     rts
  442.  
  443.     * ici dx>0, dy>0 et dx=dy
  444.     * une diagonale!!
  445. rout3
  446.                 * calcul d'adresse du 1er point dans a0
  447.     movea.l adr_ecran,a0
  448.     add.w d0,d0
  449.     adda.w d0,a0
  450.     mulu.w #ecran_largeur*2,d1
  451.     adda.l d1,a0
  452.                 * division par 2 de d5
  453.     lsr.w #1,d5
  454.     bcc ligneb3
  455.                 * si retenue alors nombre impair
  456.     move.w d4,(a0)+
  457.     adda.l d7,a0
  458.                 * ce qui permet d'afficher 2 points par 2 points
  459. ligneb3
  460.     move.w d4,(a0)+
  461.     adda.l d7,a0
  462.     move.w d4,(a0)+
  463.     adda.l d7,a0
  464.     dbra d5,ligneb3
  465.     rts
  466.  
  467.     * ici dy est nul
  468.     * et dx positif
  469.     * ligne horizontale
  470. rout4
  471.                 * calcul d'adresse du 1er point dans a0
  472.     movea.l adr_ecran,a0
  473.     add.w d0,d0
  474.     adda.w d0,a0
  475.     mulu.w #ecran_largeur*2,d1
  476.     adda.l d1,a0
  477.                 * division de d5 par 2
  478.     lsr.w #1,d5
  479.     bcc ligneb4
  480.                 * d5 : nombre impaire
  481.     move.w d4,(a0)+
  482. ligneb4
  483.     move.l d4,(a0)+        * 2 pixels d'un coup !
  484.     dbra d5,ligneb4
  485.     rts
  486.  
  487.     * ici dx est nul
  488.     * et dy est inconnu
  489.     * ligne verticale
  490. rout5
  491.     move.w d3,d6
  492.     sub.w d1,d6
  493.     bmi rout5_yneg
  494.     beq rout6
  495.                 * calcul d'adresse du 1er point dans a0
  496.     movea.l adr_ecran,a0
  497.     add.w d0,d0
  498.     adda.w d0,a0
  499.     mulu.w #ecran_largeur*2,d1
  500.     adda.l d1,a0
  501.                 * division par 2 de d6
  502.     lsr.w #1,d6
  503.     bcc ligneb5
  504.                 * d6 : nombre impaire
  505.     move.w d4,(a0)
  506.     adda.l d7,a0
  507. ligneb5
  508.     move.w d4,(a0)
  509.     adda.l d7,a0
  510.     move.w d4,(a0)
  511.     adda.l d7,a0
  512.     dbra d6,ligneb5
  513.     rts
  514. rout5_yneg
  515.     neg.w d6
  516.     neg.l d7
  517.                 * calcul d'adresse du 1er point dans a0
  518.     movea.l adr_ecran,a0
  519.     add.w d0,d0
  520.     adda.w d0,a0
  521.     mulu.w #ecran_largeur*2,d1
  522.     adda.l d1,a0
  523.                 * division par deux de d6
  524.     lsr.w #1,d6
  525.     bcc ligneb5_yneg
  526.                 * d6 : nombre impair
  527.     move.w d4,(a0)
  528.     adda.l d7,a1
  529. ligneb5_yneg
  530.     move.w d4,(a0)
  531.     adda.l d7,a0
  532.     move.w d4,(a0)
  533.     adda.l d7,a0
  534.     dbra d6,ligneb5_yneg
  535.     rts
  536.  
  537.     * deltax est nul
  538.     * deltay est nul
  539.     * c'est un point
  540.     * OK
  541. rout6
  542.                 * calcul d'adresse du 1er point dans a0
  543.     movea.l adr_ecran,a0
  544.     add.w d0,d0
  545.     adda.w d0,a0
  546.     mulu.w #ecran_largeur*2,d1
  547.     adda.l d1,a0
  548.     move.w d4,(a0)
  549.     rts
  550.  
  551.     include "principh.s"
  552.  
  553.     section BSS
  554. compteur    ds.w 1
  555.