home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / vr386 / xyclip.asm < prev   
Assembly Source File  |  1996-03-19  |  15KB  |  756 lines

  1.     TITLE    XYCLIP - SUTHERLAND-HODGEMAN CLIPPER IN ASSEMBLER
  2.  
  3.     COMMENT $
  4.  
  5. // 26/12/93 by Dave Stampe
  6. // All algorithms and code (c) 1993 by Dave Stampe
  7.  
  8. /*
  9.  This code is part of the REND386 project, created by Dave Stampe and
  10.  Bernie Roehl.
  11.  
  12.  Copyright 1992, 1993, 1994 by Dave Stampe and Bernie Roehl.
  13.  
  14.  May be freely used to write software for release into the public domain;
  15.  all commercial endeavours MUST contact BOTH Bernie Roehl and Dave Stampe
  16.  for permission to incorporate any part of this software into their
  17.  products!  Usually there is no charge for under 50-100 items for
  18.  low-cost or shareware, and terms are reasonable.  Any royalties are used
  19.  for development, so equipment is often acceptable payment.
  20.  
  21.  ATTRIBUTION:  If you use any part of this source code or the libraries
  22.  in your projects, you must give attribution to REND386, Dave Stampe,
  23.  and Bernie Roehl in your documentation, source code, and at startup
  24.  of your program.  Let's keep the freeware ball rolling!  No more
  25.  code ripoffs please.
  26.  
  27.  CONTACTS: dstampe@psych.toronto.edu, broehl@sunee.uwaterloo.ca
  28.  See the COPYRITE.H file for more information.
  29. */
  30.  
  31. This is a reasonably efficient semi-recursive XY screen clipper
  32. for polygons.  XY_clip_array() is the C call, which takes an array of
  33. (NVERTEX *) and processes to an output array.  New clipped vertices
  34. may be produced: old vertices are not discarded.
  35.  
  36.  
  37. /* Contact: dstampe@sunee.waterloo.edu */
  38.  
  39.         $
  40.  
  41.     .MODEL large
  42.     .386
  43.  
  44.  
  45.     .DATA
  46.  
  47. include 3dstruct.inc
  48. include viewdata.inc
  49.  
  50. ; clipper record variables
  51.  
  52. first_top_vtx    dd 0    ; for each level: record first, and latest vertex
  53. last_top_vtx    dd 0
  54.  
  55. first_bottom_vtx dd 0
  56. last_bottom_vtx     dd 0
  57.  
  58. first_left_vtx    dd 0
  59. last_left_vtx    dd 0
  60.  
  61. first_right_vtx    dd 0
  62. last_right_vtx    dd 0
  63.  
  64. destptr        dd 0    ; where to put output
  65. vtxcount    dw 0    ; vertex passed count
  66.  
  67. include rendmem.inc
  68.  
  69.     .CODE RENDERER
  70.  
  71. ; defined in RENDMEM.INC
  72. ; alloc new vertex
  73. ; returns new vertex in ES:BX
  74. ; BX only affected
  75.  
  76. ;ALLOCVTX  MACRO
  77. ;    les    bx,_nvalloc
  78. ;    sub    bx, SIZE NVERTEX
  79. ;    mov    _nvalloc,bx
  80. ;    mov    WORD PTR es:[bx].NV_persp,0
  81. ;      ENDM
  82.  
  83.  
  84.  
  85. ;/********** CREATE NEW INTERCEPT VERTEX **************/
  86.  
  87. ; static NVERTEX *y_intercept(NVERTEX *v1, NVERTEX *v2, long edge)
  88. ; static NVERTEX *x_intercept(NVERTEX *v1, NVERTEX *v2, long edge)
  89.  
  90. ; ARGUMENTS:
  91.  
  92. ; v1: ES:SI
  93. ; v2: ES:DI
  94. ; edge: ecx
  95. ; new, return: ES:BX
  96.  
  97.                       ; MAKES ASSUMPTION THAT ALL
  98. x1    equ    DWORD PTR es:[di].NV_xs   ; NVERTEX ARE IN SAME SEGMENT
  99. y1    equ    DWORD PTR es:[di].NV_ys
  100. z1    equ    DWORD PTR es:[di].NV_z    ; vtx 1
  101.  
  102. x2    equ    DWORD PTR es:[si].NV_xs   ; vtx 2
  103. y2    equ    DWORD PTR es:[si].NV_ys
  104. z2    equ    DWORD PTR es:[si].NV_z
  105.  
  106. xn    equ    DWORD PTR es:[bx].NV_xs   ; intercept
  107. yn    equ    DWORD PTR es:[bx].NV_ys
  108. zn    equ    DWORD PTR es:[bx].NV_z
  109.  
  110.  
  111. y_intercept    proc    near
  112.  
  113.     ALLOCVTX    ; es:bx is new vertex, assume es is renderer temp
  114.  
  115.     mov    yn,ecx
  116.     mov    ecx,y1
  117.     sub    ecx,y2
  118.     jl    fwd_clip_y    ; clip from high end to prevent roundoff
  119.     jg    rev_clip_y
  120.  
  121.     mov    eax,x1          ; no slope: copy vtx 1
  122.     mov    xn,eax
  123.     mov    eax,z1
  124.     mov    zn,eax
  125.     ret
  126.  
  127. rev_clip_y:
  128.     mov    eax,yn        ; compute new z
  129.     sub    eax,y2
  130.     mov    edx,z1
  131.     sub    edx,z2
  132.     imul    edx
  133.     idiv    ecx
  134.     add    eax,z2
  135.     mov    zn,eax
  136.  
  137.     mov    eax,yn        ; compute new x
  138.     sub    eax,y2
  139.     mov    edx,x1
  140.     sub    edx,x2
  141.     imul    edx
  142.     idiv    ecx
  143.     add    eax,x2
  144.     mov     xn,eax
  145.     ret
  146.  
  147. fwd_clip_y:
  148.     neg    ecx
  149.  
  150.     mov    eax,yn       ;  compute new z
  151.     sub    eax,y1
  152.     mov    edx,z2
  153.     sub    edx,z1
  154.     imul    edx
  155.     idiv    ecx
  156.     add    eax,z1
  157.     mov    zn,eax
  158.  
  159.     mov    eax,yn       ;  compute new x
  160.     sub    eax,y1
  161.     mov    edx,x2
  162.     sub    edx,x1
  163.     imul    edx
  164.     idiv    ecx
  165.     add    eax,x1
  166.     mov     xn,eax
  167.     ret
  168.  
  169. y_intercept    endp
  170.  
  171.  
  172.  
  173. x_intercept    proc    near
  174.  
  175.     ALLOCVTX    ; es:bx is new vertex, assume es is renderer temp
  176.  
  177.     mov    xn,ecx
  178.     mov    ecx,x1
  179.     sub    ecx,x2
  180.     jl    fwd_clip_x    ; clip from high end to prevent roundoff
  181.     jg    rev_clip_x
  182.  
  183.     mov    eax,y1          ; no slope: copy vtx 1
  184.     mov    yn,eax
  185.     mov    eax,z1
  186.     mov    zn,eax
  187.     ret
  188.  
  189. rev_clip_x:
  190.     mov    eax,xn        ; compute new z
  191.     sub    eax,x2
  192.     mov    edx,z1
  193.     sub    edx,z2
  194.     imul    edx
  195.     idiv    ecx
  196.     add    eax,z2
  197.     mov    zn,eax
  198.  
  199.     mov    eax,xn        ; compute new y
  200.     sub    eax,x2
  201.     mov    edx,y1
  202.     sub    edx,y2
  203.     imul    edx
  204.     idiv    ecx
  205.     add    eax,y2
  206.     mov     yn,eax
  207.     ret
  208.  
  209. fwd_clip_x:
  210.     neg    ecx
  211.  
  212.     mov    eax,xn       ;  compute new z
  213.     sub    eax,x1
  214.     mov    edx,z2
  215.     sub    edx,z1
  216.     imul    edx
  217.     idiv    ecx
  218.     add    eax,z1
  219.     mov    zn,eax
  220.  
  221.     mov    eax,xn       ;  compute new y
  222.     sub    eax,x1
  223.     mov    edx,y2
  224.     sub    edx,y1
  225.     imul    edx
  226.     idiv    ecx
  227.     add    eax,y1
  228.     mov     yn,eax
  229.     ret
  230.  
  231. x_intercept    endp
  232.  
  233.  
  234.  
  235. ;/************* CLIPPER C INTERFACE **********/
  236.  
  237. ; XY clip an array of vertices, store in array
  238. ; returns number of vertices produced
  239. ;
  240. ; int XY_clip_array(NVERTEX **src, NVERTEX **dest, int count);
  241.  
  242. src    equ    DWORD PTR [bp+8]          ; arguments
  243. dest    equ    DWORD PTR [bp+12]
  244. count    equ    WORD PTR [bp+16]
  245.  
  246. srcptr  equ    DWORD PTR [bp-4]    ; locals
  247. n    equ    WORD PTR  [bp-8]    ; vertex counter
  248.  
  249.  
  250. ;CHECKMEM  MACRO num_vertex         ;; DEFINED IN RENDMEM.INC
  251. ;    mov  ax,num_vertex
  252. ;    imul ax,SIZE NVERTEX
  253. ;    add  ax,200
  254. ;    add  ax,WORD PTR _npalloc
  255. ;    neg  ax
  256. ;    add  ax,WORD PTR _nvalloc    ; carry clear if out of memory
  257. ;      ENDM
  258.  
  259.  
  260.     PUBLIC    _XY_clip_array
  261.  
  262. _XY_clip_array    proc    far
  263.  
  264.     push    ebp
  265.     mov    ebp,esp
  266.     sub    esp,16
  267.  
  268.     push    esi
  269.     push    edi
  270.     push    ecx
  271.     push    edx
  272.  
  273.     mov    last_top_vtx,0         ; reset clipper variables
  274.     mov    last_bottom_vtx,0
  275.     mov    last_left_vtx,0
  276.     mov    last_right_vtx,0
  277.     mov    vtxcount,0
  278.  
  279.     mov    eax,src
  280.     mov     srcptr,eax
  281.     mov    eax,dest
  282.     mov    destptr,eax
  283.     mov    ax,count
  284.     mov    n,ax
  285.                    ; enough mem for all vtxs?
  286.     CHECKMEM 10
  287.     jc    have_memory
  288.     mov     vtxcount,-1
  289.     jmp    exit_clip
  290.  
  291. have_memory:
  292. next_clip:
  293.     mov    ax,OTOP            ; call top level of clipper
  294.     push    ax
  295.     les    bx,srcptr
  296.     mov    eax,es:[bx]
  297.     push    eax
  298.     call    near ptr XY_clip
  299.     add    esp,6
  300.  
  301.     add    srcptr,4
  302.     dec    n
  303.     jne    next_clip
  304.  
  305.     cmp    count,2
  306.     jle    exit_clip
  307.  
  308.     mov    ax,OTOP        ; flush clipper
  309.     push    ax
  310.     xor    eax,eax
  311.     push    eax
  312.     call    near ptr XY_clip
  313.     add    esp,6
  314.  
  315.  
  316. exit_clip:
  317.     mov    ax,vtxcount
  318.  
  319.     pop    edx
  320.     pop    ecx
  321.     pop    edi
  322.     pop    esi
  323.  
  324.     mov    esp,ebp
  325.     pop    ebp
  326.     ret
  327.  
  328. _XY_clip_array    endp
  329.  
  330.  
  331.  
  332.  
  333. ;/************ RECURSIVE CLIPPER KERNAL *************/
  334.  
  335. ;static void XY_clip(NVERTEX *vtx, int stage)
  336. ;      /* XY semirecursive clipper           */
  337. ;      /* set last = NULL before first call     */
  338. ;      /* call with all (copied) vertices      */
  339. ;      /* call with NULL to flush           */
  340. ;      /* also copies output to poly table     */
  341.  
  342. vtx    equ    DWORD PTR [bp+6]          ; arguments
  343. stage    equ    WORD PTR [bp+10]    ; FOR NEAR CALL OFFSETS
  344.  
  345. XY_clip    proc    near
  346.  
  347.     push    ebp        ; generic entry
  348.     mov    ebp,esp
  349.  
  350.     mov    ax,stage        ; find stage
  351.     cmp    ax,OTOP
  352.     je    top_clip
  353.     cmp    ax,ORIGHT
  354.     je    right_clip
  355.     cmp    ax,OBOTTOM
  356.     je    bottom_clip
  357.     jmp    left_clip
  358.  
  359. XY_clip_bottom:                ; fast local entries
  360.     push    ebp
  361.     mov    ebp,esp
  362.     jmp    bottom_clip
  363.  
  364. XY_clip_left:
  365.     push    ebp
  366.     mov    ebp,esp
  367.     jmp    left_clip
  368.  
  369. XY_clip_right:
  370.     push    ebp
  371.     mov    ebp,esp
  372.     jmp    right_clip
  373.  
  374. XY_clip_top:
  375.     push    ebp
  376.     mov    ebp,esp
  377.  
  378.  
  379.     ;;;;;;;; START OF TOP CLIP;;;;;;;;;;;
  380.  
  381. top_clip:
  382.     mov    eax,DWORD PTR last_top_vtx   ; is this the first?
  383.     or    eax,eax
  384.     jnz    not_first_top
  385.  
  386.     or     eax,vtx        ; traps NULL if first=last
  387.     je    right_clip
  388.     mov    last_top_vtx,eax             ; record
  389.     mov    first_top_vtx,eax
  390.     les    bx,vtx
  391.     mov    al,BYTE PTR es:[bx].NV_ocode ; pass if in window
  392.     test    al,OTOP            ; we can use outcode on first only
  393.     jnz    end_XY_clip
  394.     jmp    right_clip
  395.  
  396. not_first_top:                    ; OK, we've got an edge
  397.     mov    eax,DWORD PTR vtx
  398.     or    eax,eax
  399.     jnz    not_flush_top     ; NULL to flush clipper
  400.  
  401.     les    si,first_top_vtx             ; look for window top crossing
  402.     mov    al,BYTE PTR es:[si].NV_ocode
  403.     les    di,last_top_vtx
  404.     xor    al,BYTE PTR es:[di].NV_ocode
  405.     test    al,OTOP
  406.     jz     right_clip
  407.  
  408. ;   nv = y_intercept(first_top_vtx, last_top_vtx, VS_top4);
  409. ;   XY_clip(nv,RIGHT);            /* process this new point */
  410.  
  411.     mov    ecx,_VS_top4    ; si,di,es already loaded
  412.     call    y_intercept     ; create intercept vertex
  413.     push    es
  414.     push    bx
  415.     call    near ptr XY_clip_right   ; and clip it
  416.     add    esp,4
  417.     jmp    right_clip      ; continue to flush
  418.  
  419. not_flush_top:
  420.     les    si,vtx
  421.     mov    al,BYTE PTR es:[si].NV_ocode
  422.     push    ax
  423.     les    di,last_top_vtx
  424.     xor    al,BYTE PTR es:[di].NV_ocode
  425.     test    al,OTOP
  426.     jz    do_top_clip
  427.  
  428.     mov    ecx,_VS_top4    ; si,di,es already loaded
  429.     call    y_intercept     ; create intercept vertex
  430.     push    es
  431.     push    bx              ; and clip it
  432.     call    near ptr XY_clip_right
  433.     add    esp,4           ; continue with original vertex
  434.  
  435. do_top_clip:
  436.     mov    eax,vtx         ; ave as last vertex
  437.     mov    last_top_vtx,eax
  438.     pop    ax
  439.     test    al,OTOP        ; was vertex in window?
  440.     jnz    end_XY_clip    ; no: discard it
  441.  
  442.  
  443.     ;;;;;;;; START OF RIGHT CLIP;;;;;;;;;;;
  444.  
  445. right_clip:
  446.     mov    eax, last_right_vtx
  447.     or    eax,eax
  448.     jnz    not_first_right
  449.  
  450.     or     eax, vtx
  451.     je    bottom_clip
  452.  
  453.     mov    last_right_vtx,eax       ; first vertex
  454.     mov    first_right_vtx,eax
  455.     les    bx, vtx
  456.     mov    eax, es:[bx].NV_xs
  457.     cmp    eax, _VS_right4
  458.     jg    end_XY_clip
  459.     jmp    bottom_clip
  460.  
  461. not_first_right:
  462.     mov    eax, vtx
  463.     or    eax,eax
  464.     jnz    not_flush_right
  465.  
  466.     les    si, first_right_vtx      ; flush: test for in-out pair
  467.     mov    eax, es:[si].NV_xs
  468.     cmp    eax, _VS_right4
  469.     jle    pas1b
  470.  
  471.     les    di, last_right_vtx
  472.     mov    eax, es:[di].NV_xs
  473.     cmp    eax, _VS_right4
  474.     jle    pas2b
  475.     jmp    bottom_clip
  476. pas1b:
  477.     les    di, last_right_vtx
  478.     mov    eax, es:[di].NV_xs
  479.     cmp    eax, _VS_right4
  480.     jg    pas2b
  481.     jmp    bottom_clip
  482.  
  483. pas2b:
  484. ;   nv = x_intercept(first_right_vtx, last_right_vtx, VS_right4);
  485. ;   XY_clip(nv,BOTTOM);            /* process this new point */
  486.  
  487.     mov    ecx,_VS_right4    ; si,di,es already loaded
  488.     call    x_intercept     ; create intercept vertex
  489.     push    es
  490.     push    bx
  491.     call    near ptr XY_clip_bottom  ; and clip it
  492.     add    esp,4
  493.     jmp    bottom_clip     ; continue to flush
  494.  
  495. not_flush_right:                      ; full in-out test
  496.     les    si, vtx
  497.     mov    eax, es:[si].NV_xs
  498.     cmp    eax, _VS_right4
  499.     jle    pat1b
  500.  
  501.     les    di, last_right_vtx
  502.     mov    eax, es:[di].NV_xs
  503.     cmp    eax, _VS_right4
  504.     jg    no_right_clip
  505.  
  506. ;   nv = x_intercept(vtx, last_right_vtx, VS_right4);
  507. ;   XY_clip(nv,BOTTOM);            /* process this new point */
  508.  
  509.     mov    ecx,_VS_right4    ; si,di,es already loaded
  510.     call    x_intercept     ; create intercept vertex
  511.     push    es
  512.     push    bx
  513.     call    near ptr XY_clip_bottom  ; and clip it
  514.     add    esp,4
  515.  
  516. no_right_clip:
  517.     mov    eax, vtx             ; save
  518.     mov    last_right_vtx,eax   ; was outside, so junk vtx
  519.     jmp    end_XY_clip
  520.  
  521. pat1b:                 ; in-window test cont'd
  522.     les    di, last_right_vtx
  523.     mov    eax, es:[di].NV_xs
  524.     cmp    eax, _VS_right4
  525.     jle    do_right_clip
  526.  
  527. ;   nv = x_intercept(vtx, last_right_vtx, VS_right4);
  528. ;   XY_clip(nv,BOTTOM);            /* process this new point */
  529.  
  530.     mov    ecx,_VS_right4    ; si,di,es already loaded
  531.     call    x_intercept     ; create intercept vertex
  532.     push    es
  533.     push    bx
  534.     call    near ptr XY_clip_bottom  ; and clip it
  535.     add    esp,4
  536.  
  537. do_right_clip:
  538.     mov    eax, vtx        ; was in window: continue
  539.     mov    last_right_vtx,eax
  540.  
  541.  
  542.     ;;;;;;;; START OF BOTTOM CLIP;;;;;;;;;;;
  543.  
  544. bottom_clip:
  545.     mov    eax, last_bottom_vtx
  546.     or    eax,eax
  547.     jnz    not_first_bottom
  548.     or     eax, vtx
  549.     je    left_clip
  550.     mov    last_bottom_vtx,eax
  551.     mov    first_bottom_vtx,eax
  552.     les    bx, vtx
  553.     mov    eax, es:[bx].NV_ys
  554.     cmp    eax, _VS_bottom4
  555.     jg    end_XY_clip
  556.     jmp    left_clip
  557.  
  558. not_first_bottom:
  559.     mov    eax, vtx
  560.     or    eax,eax
  561.     jnz    not_flush_bottom
  562.     les    si, first_bottom_vtx
  563.     mov    eax, es:[si].NV_ys
  564.     cmp    eax, _VS_bottom4
  565.     jle    pas1bb
  566.  
  567.     les    di, last_bottom_vtx
  568.     mov    eax, es:[di].NV_ys
  569.     cmp    eax, _VS_bottom4
  570.     jle    pas2bb
  571.     jmp     left_clip
  572.  
  573. pas1bb:
  574.     les    di, last_bottom_vtx
  575.     mov    eax, es:[di].NV_ys
  576.     cmp    eax, _VS_bottom4
  577.     jg    pas2bb
  578.     jmp    left_clip
  579.  
  580. pas2bb:
  581. ;   nv = y_intercept(first_bottom_vtx, last_bottom_vtx, VS_bottom4);
  582. ;   XY_clip(nv,LEFT);            /* process this new point */
  583.  
  584.     mov    ecx,_VS_bottom4    ; si,di,es already loaded
  585.     call    y_intercept     ; create intercept vertex
  586.     push    es
  587.     push    bx
  588.     call    near ptr XY_clip_left   ; and clip it
  589.     add    esp,4
  590.     jmp    left_clip    ; continue flush
  591.  
  592. not_flush_bottom:
  593.     les    si, vtx
  594.     mov    eax, es:[si].NV_ys
  595.     cmp    eax, _VS_bottom4
  596.     jle    pat1t
  597.  
  598.     les    di, last_bottom_vtx
  599.     mov    eax, es:[di].NV_ys
  600.     cmp    eax, _VS_bottom4
  601.     jg    no_bottom_clip
  602.  
  603. ;   nv = y_intercept(vtx, last_bottom_vtx, VS_bottom4);
  604. ;   XY_clip(nv,LEFT);            /* process this new point */
  605.  
  606.     mov    ecx,_VS_bottom4    ; si,di,es already loaded
  607.     call    y_intercept     ; create intercept vertex
  608.     push    es
  609.     push    bx
  610.     call    near ptr XY_clip_left    ; and clip it
  611.     add    esp,4
  612.  
  613. no_bottom_clip:
  614.     mov    eax, vtx
  615.     mov    last_bottom_vtx,eax
  616.     jmp     end_XY_clip          ; out, so discard it
  617.  
  618. pat1t:
  619.     les    di, last_bottom_vtx
  620.     mov    eax, es:[di].NV_ys
  621.     cmp    eax, _VS_bottom4
  622.     jle    do_bottom_clip
  623.  
  624. ;   nv = y_intercept(vtx, last_bottom_vtx, VS_bottom4);
  625. ;   XY_clip(nv,LEFT);            /* process this new point */
  626.  
  627.     mov    ecx,_VS_bottom4    ; si,di,es already loaded
  628.     call    y_intercept     ; create intercept vertex
  629.     push    es
  630.     push    bx
  631.     call    near ptr XY_clip_left    ; and clip it
  632.     add    esp,4           ; in, so continue
  633.  
  634. do_bottom_clip:
  635.     mov    eax, vtx
  636.     mov    last_bottom_vtx,eax
  637.  
  638.  
  639.     ;;;;;;;; START OF LEFT CLIP;;;;;;;;;;;
  640.  
  641. left_clip:
  642.     mov    eax, last_left_vtx
  643.     or    eax,eax
  644.     jnz    not_first_left
  645.  
  646.     or     eax, vtx
  647.     je    end_XY_clip
  648.  
  649.     mov    last_left_vtx,eax
  650.     mov    first_left_vtx,eax
  651.     les    bx, vtx
  652.     mov    eax, es:[bx].NV_xs
  653.     cmp    eax, _VS_left4
  654.     jl    end_XY_clip
  655.     jmp    do_left_clip
  656.  
  657. not_first_left:
  658.     mov    eax, vtx
  659.     or    eax,eax
  660.     jnz    not_flush_left
  661.     les    si, first_left_vtx
  662.     mov    eax, es:[si].NV_xs
  663.     cmp    eax, _VS_left4
  664.     jge    pas1x
  665.  
  666.     les    di, last_left_vtx
  667.     mov    eax, es:[di].NV_xs
  668.     cmp    eax, _VS_left4
  669.     jge     pas2x
  670.     jmp    end_XY_clip
  671.  
  672. pas1x:
  673.     les    di, last_left_vtx
  674.     mov    eax, es:[di].NV_xs
  675.     cmp    eax, _VS_left4
  676.     jge    end_XY_clip
  677.  
  678. pas2x:
  679. ;   nv = x_intercept(first_left_vtx, last_left_vtx, VS_left4);
  680.  
  681.     mov    ecx,_VS_left4    ; si,di,es already loaded
  682.     call    x_intercept     ; create intercept vertex
  683.     mov    ax,es        ; build far ptr
  684.     shl    eax,16
  685.     mov    ax,bx
  686.     les    di,destptr
  687.     add    destptr,4
  688.     mov    es:[di],eax    ; store new vertex ptr
  689.     inc    vtxcount
  690.     jmp    end_XY_clip
  691.  
  692. not_flush_left:
  693.     les    si, vtx
  694.     mov    eax, es:[si].NV_xs
  695.     cmp    eax, _VS_left4
  696.     jge    pat1x
  697.  
  698.     les    di, last_left_vtx
  699.     mov    eax, es:[di].NV_xs
  700.     cmp    eax, _VS_left4
  701.     jl    no_left_clip
  702.  
  703. ;   nv = x_intercept(vtx, last_left_vtx, VS_left4);
  704.  
  705.     mov    ecx,_VS_left4    ; si,di,es already loaded
  706.     call    x_intercept     ; create intercept vertex
  707.     mov    ax,es        ; build far ptr
  708.     shl    eax,16
  709.     mov    ax,bx
  710.     les    di,destptr
  711.     add    destptr,4
  712.     mov    es:[di],eax    ; store new vertex ptr
  713.     inc    vtxcount
  714.  
  715. no_left_clip:
  716.     mov    eax, vtx
  717.     mov    last_left_vtx,eax
  718.     jmp    end_XY_clip
  719.  
  720. pat1x:
  721.     les    di, last_left_vtx
  722.     mov    eax, es:[di].NV_xs
  723.     cmp    eax, _VS_left4
  724.     jge    do_left_clip
  725.  
  726. ;   nv = x_intercept(vtx, last_left_vtx, VS_left4);
  727.  
  728.     mov    ecx,_VS_left4    ; si,di,es already loaded
  729.     call    x_intercept     ; create intercept vertex
  730.     mov    ax,es        ; build far ptr
  731.     shl    eax,16
  732.     mov    ax,bx
  733.     les    di,destptr
  734.     add    destptr,4
  735.     mov    es:[di],eax    ; store new vertex ptr
  736.     inc    vtxcount
  737.  
  738. do_left_clip:
  739.     mov    eax, vtx
  740.     mov    last_left_vtx,eax
  741.     les    di,destptr
  742.     add    destptr,4
  743.     mov    es:[di],eax    ; store new vertex ptr
  744.     inc    vtxcount
  745.  
  746. end_XY_clip:
  747.     mov    esp,ebp
  748.     pop    ebp
  749.     ret
  750.  
  751. XY_clip        endp
  752.  
  753.  
  754.     end
  755.  
  756.