home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / 3d / clipper.asm < prev    next >
Assembly Source File  |  1998-06-08  |  9KB  |  383 lines

  1. ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  2. ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  3. ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  4. ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  5. ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  6. ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  7. ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  8. ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  9. ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  10. ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  11. ;
  12. ; $Source: f:/miner/source/3d/rcs/clipper.asm $
  13. ; $Revision: 1.6 $
  14. ; $Author: matt $
  15. ; $Date: 1994/07/25 00:00:02 $
  16. ;
  17. ; Source for clipper
  18. ;
  19. ; $Log: clipper.asm $
  20. ; Revision 1.6  1994/07/25  00:00:02  matt
  21. ; Made 3d no longer deal with point numbers, but only with pointers.
  22. ; Revision 1.5  1994/02/10  18:00:38  matt
  23. ; Changed 'if DEBUG_ON' to 'ifndef NDEBUG'
  24. ; Revision 1.4  1994/01/13  15:39:09  mike
  25. ; Change usage of Frame_count to _Frame_count
  26. ; Revision 1.3  1993/11/04  18:48:39  matt
  27. ; Added system to only rotate points once per frame
  28. ; Revision 1.2  1993/11/04  12:36:25  mike
  29. ; Add clipping for lighting value.
  30. ; Revision 1.1  1993/10/29  22:20:27  matt
  31. ; Initial revision
  32. ;
  33. ;
  34.  
  35. .386
  36.     option    oldstructs
  37.  
  38.     .nolist
  39.     include    types.inc
  40.     include    psmacros.inc
  41.     include    gr.inc
  42.     include    3d.inc
  43.     .list
  44.  
  45.     assume    cs:_TEXT, ds:_DATA
  46.  
  47. _DATA    segment    dword public USE32 'DATA'
  48.  
  49. rcsid    db    "$Id: clipper.asm 1.6 1994/07/25 00:00:02 matt Exp $"
  50.     align    4
  51.  
  52.  public free_point_num
  53.  
  54. ;buffer of temp points for when clipping creates a new point
  55. temp_points    db    MAX_POINTS_IN_POLY * size g3s_point dup (?)
  56.  
  57. free_points    label    dword
  58. p = temp_points
  59.     rept    MAX_POINTS_IN_POLY
  60.      dd    p
  61.      p = p+size g3s_point
  62.     endm
  63.  
  64. free_point_num    dd    0
  65.     
  66. ;Vars for polygon clipper
  67.  
  68. nverts    dd    ?    ;number of verts in poly
  69. nv_cnt    dd    ?    ;loop variable
  70.  
  71. plane    db    ?
  72.  
  73. _DATA    ends
  74.  
  75.  
  76.  
  77. _TEXT    segment    dword public USE32 'CODE'
  78.  
  79. ;get a temporary point. returns ebp=point.
  80. get_temp_point:    mov    ebp,free_point_num
  81.     mov    ebp,free_points[ebp*4]
  82.     inc    free_point_num
  83.     mov    [ebp].p3_flags,PF_TEMP_POINT    ;clear proj,set temp
  84.     ifndef    NDEBUG
  85.      cmp    free_point_num,MAX_POINTS_IN_POLY
  86.      break_if    e,"temp_point buf empty!"
  87.     endif
  88.     ret
  89.  
  90. ;free a temporary point. takes esi=point
  91. free_temp_point:    push    eax
  92.     dec    free_point_num
  93.     mov    eax,free_point_num
  94.     mov    free_points[eax*4],esi
  95.     pop    eax
  96.     ret
  97.  
  98. ;clip a particular value (eg. x, y, u). 
  99. ;assumes esi,edi=start,end points, ebp=dest point, and ebx/ecx=fraction
  100. ;stores new value and returns it in eax
  101. clip_value    macro    ofs
  102.     mov    eax,[edi].ofs    ;end
  103.     sub    eax,[esi].ofs    ;-start
  104.     imul    ebx
  105.     idiv    ecx
  106.     add    eax,[esi].ofs    ;+start
  107.     mov    [ebp].ofs,eax
  108.     endm
  109.  
  110. ;clips an edge against one plane. 
  111. ;takes esi (on) ,edi (off)=points, cl=plane flag (1,2,4,8 = left,right,bot,top)
  112. ;returns esi,edi=clipped points (edi new), bl=codes
  113. ;trashes eax,edx,ebp
  114. clip_edge:
  115.  
  116. ;compute clipping value k = (xs-zs) / (xs-xe-zs+ze)
  117. ;use x or y as appropriate, and negate x/y value as appropriate
  118.  
  119.     mov    ebx,[esi].x    ;eax = xs
  120.     mov    edx,[edi].x    ;ebx = xe
  121.  
  122.     test    cl,CC_OFF_TOP+CC_OFF_BOT    ;top or bot (y)?
  123.     jz    not_y
  124.     mov    ebx,[esi].y    ;eax = ys
  125.     mov    edx,[edi].y    ;ebx = ye
  126. not_y:
  127.     test    cl,CC_OFF_LEFT+CC_OFF_BOT ;right or top (neg)?
  128.     jz    not_neg
  129.     neg    ebx
  130.     neg    edx
  131. not_neg:
  132.     mov    plane,cl    ;store
  133.     push    ecx    ;save plane
  134.  
  135.     sub    ebx,[esi].z    ;ebx = xs-zs
  136.     mov    ecx,ebx    ;ecx = xs-zs
  137.     sub    ecx,edx    ;edx = xs-xe-zs
  138.     add    ecx,[edi].z    ;edx = xs-xe+zs+ze
  139.  
  140. ;now frac=ebx/ecx
  141.  
  142.     call    get_temp_point    ;ret ebp=point
  143.     ;;mov    ax,_Frame_count
  144.     ;;mov    [ebp].p3_frame,ax    ;this point valid 
  145.  
  146.     clip_value x
  147.     mov    [ebp].z,eax    ;assume z=x
  148.  
  149.     clip_value y
  150.  
  151.     test    plane,CC_OFF_TOP+CC_OFF_BOT    ;top or bot (y)?
  152.     jz    not_y2
  153.     mov    [ebp].z,eax    ;z=y
  154. not_y2:
  155.  
  156. ;check if uv values present, and clip if so
  157.     test    [esi].p3_flags,PF_UVS    ;uv values here?
  158.     jz    no_clip_uv    ;..nope
  159.  
  160.     clip_value p3_u
  161.     clip_value p3_v
  162.     or    [ebp].p3_flags,PF_UVS    ;new point has uv set
  163. no_clip_uv:
  164.  
  165. ;check if lv values present, and clip if so
  166.     test    [esi].p3_flags,PF_LVS    ;lv values here?
  167.     jz    no_clip_lv    ;..nope
  168.  
  169.     clip_value p3_l
  170.     or    [ebp].p3_flags,PF_LVS    ;new point has lv set
  171. no_clip_lv:
  172.     pop    ecx    ;get plane back
  173.  
  174. ;negate z if clipping against left or bot
  175.     test    cl,CC_OFF_LEFT+CC_OFF_BOT ;right or top (neg)?
  176.     jz    not_neg2
  177.     neg    [ebp].z    ;z=-x (or -y)
  178. not_neg2:
  179.  
  180. ;see if discarded point is temp point, and free it if so
  181.  
  182.     mov    edi,ebp    ;return correct point
  183.     mov    eax,edi
  184.     jmp    code_point    ;returns bl=codes
  185.  
  186.  
  187. ;clips a line to the viewing pyramid.
  188. ;takes esi,edi=points (pointers), al=codes_or
  189. ;return esi,edi=clipped points, one or both new
  190. clip_line:    pushm    ebx,ecx,edx,ebp
  191.  
  192.     mov    ecx,1    ;plane flag
  193.  
  194. l_plane_loop:    test    al,cl    ;off this plane?
  195.     jz    l_not_this_plane
  196.  
  197.     test    [esi].p3_codes,cl    ;this one on?
  198.     jz    order_ok    ;..yep
  199.     xchg    esi,edi    ;..nope
  200. order_ok:
  201.     push    edi    ;save old off-screen point
  202.     call    clip_edge    ;esi=on, edi=off
  203.             ;returns bl=new edi codes
  204.  
  205.     pop    eax    ;get discarded point
  206. ;see if must free rejected point
  207.     test    [eax].p3_flags,PF_TEMP_POINT
  208.     jz    not_temp_eax
  209.     xchg    esi,eax
  210.     call    free_temp_point
  211.     mov    esi,eax
  212. not_temp_eax:
  213.  
  214.     mov    al,[esi].p3_codes    ;get esi codes
  215.     test    al,bl    ;clipped away?
  216.     jnz    l_clipped_away    ;..yep
  217.     or    al,bl    ;get new codes_or
  218. l_not_this_plane:
  219.     add    ecx,ecx    ;next plane
  220.     cmp    ecx,16    ;done?
  221.     jne    l_plane_loop    ;..nope
  222.  
  223. l_clipped_away:    popm    ebx,ecx,edx,ebp
  224.     ret
  225.  
  226.  
  227. ;TEMPORARY - inline this code when working
  228. ;takes esi,edi=lists
  229. ;returns edi=end of new list, dx=new codes. trashes eax,ebx,edx,ebp,esi
  230. clip_plane:
  231.     mov    ebx,nverts
  232.  
  233. ;copy first two verts to end
  234.     mov    eax,[esi]
  235.     mov    [esi+ebx*4],eax
  236.     mov    eax,4[esi]
  237.     mov    4[esi+ebx*4],eax
  238.  
  239.     mov    nv_cnt,ebx    ;loop variable
  240.  
  241.     add    esi,4    ;point at second
  242.  
  243.     mov    edx,0ff00h    ;initialize codes
  244.  
  245. point_loop:    mov    eax,[esi]    ;get current point
  246.     add    esi,4
  247.  
  248. ;go though list of points. 
  249.  
  250.     test    [eax].p3_codes,cl    ;cur point off?
  251.     jz    cur_not_off    ;..nope
  252.  
  253. ;cur point is off. check prev and next
  254.  
  255.     mov    ebx,[esi-8]    ;get prev
  256.     test    [ebx].p3_codes,cl    ;prev off?
  257.     jnz    prev_off    ;..yup, so nothing to clip
  258.  
  259.     push    eax    ;save current point
  260.  
  261. ;must clip cur (off screen) to prev (on screen)
  262.     pushm    edx,esi,edi    ;save codes,list pointers
  263.  
  264.     mov    esi,ebx    ;esi=on screen
  265.     mov    edi,eax    ;edi=off screen
  266.     call    clip_edge
  267.     mov    eax,edi    ;save new point
  268.  
  269.     popm    edx,esi,edi    ;get codes,list pointers
  270.  
  271.     mov    [edi],eax    ;store in dest list
  272.     add    edi,4
  273.     or    dl,bl    ;update codes_or
  274.     and    dh,bl    ;update codes_and
  275.  
  276.     pop    eax    ;restore current point
  277. prev_off:
  278.     mov    ebx,[esi]    ;get next
  279.     test    [ebx].p3_codes,cl    ;next off?
  280.     jnz    next_off    ;..yes
  281.  
  282.     push    eax    ;save current point
  283.  
  284. ;must clip cur (off screen) to next (on screen)
  285.     pushm    edx,esi,edi    ;save codes,list pointers
  286.  
  287.     mov    esi,ebx    ;esi=on screen
  288.     mov    edi,eax    ;edi=off screen
  289.     call    clip_edge
  290.     mov    eax,edi    ;save new point
  291.  
  292.     popm    edx,esi,edi    ;get codes,list pointers
  293.  
  294.     mov    [edi],eax    ;store in dest list
  295.     add    edi,4
  296.     or    dl,bl    ;update codes_or
  297.     and    dh,bl    ;update codes_and
  298.  
  299.     pop    eax    ;get current back
  300. next_off:
  301.  
  302. ;see if must free discarded point
  303.     test    [eax].p3_flags,PF_TEMP_POINT
  304.     jz    not_temp
  305.     xchg    esi,eax
  306.     call    free_temp_point
  307.     mov    esi,eax
  308. not_temp:
  309.  
  310.     jmp    do_next_point
  311.  
  312. cur_not_off:    mov    [edi],eax    ;store cur in dest buffer
  313.     add    edi,4
  314.     or    dl,[eax].p3_codes    ;update codes_or
  315.     and    dh,[eax].p3_codes    ;update codes_and
  316.  
  317. do_next_point:    dec    nv_cnt
  318.     jnz    point_loop
  319.  
  320.     ret
  321.  
  322.  
  323. ;3d clip a polygon.  
  324. ;takes esi=src list, edi=dest list, ecx=nverts, al=codes_or
  325. ;returns esi=list of clipped points, some of them new, ecx=new nverts, dx=codes
  326. ;esi at exit will be either of esi,edi at entry
  327. clip_polygon:    push    ebp
  328.  
  329.     mov    nverts,ecx    ;save
  330.  
  331. ;now loop through each plane, a-clipping as we go
  332.  
  333.     mov    ecx,1    ;plane flag
  334.  
  335.     mov    dl,al    ;dl = codes_or 
  336.  
  337. ;clipping from [esi] -> [edi]
  338. p_plane_loop:    test    dl,cl    ;off this plane?
  339.     jz    p_not_this_plane
  340.  
  341.     push    esi    ;save src ptr
  342.     push    edi    ;save dest ptr
  343.  
  344. ;clip against this plane
  345.     call    clip_plane    ;when working, inline this code
  346.  
  347. ;done clip for this plane
  348.     mov    eax,edi    ;end of dest loop
  349.     pop    esi    ;get start of dest buffer
  350.  
  351.     sub    eax,esi    ;get delta
  352.     sar    eax,2    ;get new vert count
  353.     mov    nverts,eax    ;save new value
  354.  
  355.     pop    edi    ;new dest = old scr
  356.  
  357.     test    dh,dh    ;check new codes_and
  358.     jnz    p_clipped_away    ;polygon all off screen
  359.  
  360. p_not_this_plane:    add    ecx,ecx    ;next plane
  361.     cmp    ecx,16    ;done?
  362.     jne    p_plane_loop    ;..nope
  363.  
  364. p_clipped_away:    pop    ebp
  365.     mov    ecx,nverts    ;new value
  366.     ret
  367.  
  368.  
  369. _TEXT    ends
  370.  
  371.  
  372.  
  373. ;should I write a combined clipper/projector?
  374.  
  375.     end
  376.  
  377.