CLIPPER.ASM 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  11. .386
  12. option oldstructs
  13. .nolist
  14. include pstypes.inc
  15. include psmacros.inc
  16. include gr.inc
  17. include 3d.inc
  18. .list
  19. assume cs:_TEXT, ds:_DATA
  20. _DATA segment dword public USE32 'DATA'
  21. rcsid db "$Id: clipper.asm 1.10 1996/02/14 09:59:55 matt Exp $"
  22. align 4
  23. public free_point_num
  24. ;buffer of temp points for when clipping creates a new point
  25. temp_points db MAX_POINTS_IN_POLY * size g3s_point dup (?)
  26. free_points label dword
  27. p = temp_points
  28. rept MAX_POINTS_IN_POLY
  29. dd p
  30. p = p+size g3s_point
  31. endm
  32. free_point_num dd 0
  33. ;Vars for polygon clipper
  34. nverts dd ? ;number of verts in poly
  35. nv_cnt dd ? ;loop variable
  36. plane db ?
  37. _DATA ends
  38. _TEXT segment dword public USE32 'CODE'
  39. ;get a temporary point. returns ebp=point.
  40. get_temp_point: mov ebp,free_point_num
  41. mov ebp,free_points[ebp*4]
  42. inc free_point_num
  43. mov [ebp].p3_flags,PF_TEMP_POINT ;clear proj,set temp
  44. ifndef NDEBUG
  45. cmp free_point_num,MAX_POINTS_IN_POLY
  46. break_if e,"temp_point buf empty!"
  47. endif
  48. ret
  49. ;free a temporary point. takes esi=point
  50. free_temp_point: push eax
  51. dec free_point_num
  52. mov eax,free_point_num
  53. mov free_points[eax*4],esi
  54. pop eax
  55. ret
  56. ;initialize the free points
  57. reset_temp_points: debug_brk 'how often does this get called?'
  58. pushm edi,eax,ecx
  59. mov free_point_num,0
  60. lea edi,free_points
  61. lea eax,temp_points
  62. mov ecx,MAX_POINTS_IN_POLY
  63. reset_loop: stosd
  64. add eax,size g3s_point
  65. loop reset_loop
  66. popm edi,eax,ecx
  67. ret
  68. ;clip a particular value (eg. x, y, u).
  69. ;assumes esi,edi=start,end points, ebp=dest point, and ebx/ecx=fraction
  70. ;stores new value and returns it in eax
  71. clip_value macro ofs
  72. mov eax,[edi].ofs ;end
  73. sub eax,[esi].ofs ;-start
  74. imul ebx
  75. idiv ecx
  76. add eax,[esi].ofs ;+start
  77. mov [ebp].ofs,eax
  78. endm
  79. ;clips an edge against one plane.
  80. ;takes esi (on) ,edi (off)=points, cl=plane flag (1,2,4,8 = left,right,bot,top)
  81. ;returns esi,edi=clipped points (edi new), bl=codes
  82. ;trashes eax,edx,ebp
  83. clip_edge:
  84. ;compute clipping value k = (xs-zs) / (xs-xe-zs+ze)
  85. ;use x or y as appropriate, and negate x/y value as appropriate
  86. mov ebx,[esi].x ;eax = xs
  87. mov edx,[edi].x ;ebx = xe
  88. test cl,CC_OFF_TOP+CC_OFF_BOT ;top or bot (y)?
  89. jz not_y
  90. mov ebx,[esi].y ;eax = ys
  91. mov edx,[edi].y ;ebx = ye
  92. not_y:
  93. test cl,CC_OFF_LEFT+CC_OFF_BOT ;right or top (neg)?
  94. jz not_neg
  95. neg ebx
  96. neg edx
  97. not_neg:
  98. mov plane,cl ;store
  99. push ecx ;save plane
  100. sub ebx,[esi].z ;ebx = xs-zs
  101. mov ecx,ebx ;ecx = xs-zs
  102. sub ecx,edx ;edx = xs-xe-zs
  103. add ecx,[edi].z ;edx = xs-xe+zs+ze
  104. ;now frac=ebx/ecx
  105. call get_temp_point ;ret ebp=point
  106. ;;mov ax,_Frame_count
  107. ;;mov [ebp].p3_frame,ax ;this point valid
  108. clip_value x
  109. mov [ebp].z,eax ;assume z=x
  110. clip_value y
  111. test plane,CC_OFF_TOP+CC_OFF_BOT ;top or bot (y)?
  112. jz not_y2
  113. mov [ebp].z,eax ;z=y
  114. not_y2:
  115. ;check if uv values present, and clip if so
  116. test [esi].p3_flags,PF_UVS ;uv values here?
  117. jz no_clip_uv ;..nope
  118. clip_value p3_u
  119. clip_value p3_v
  120. or [ebp].p3_flags,PF_UVS ;new point has uv set
  121. no_clip_uv:
  122. ;check if lv values present, and clip if so
  123. test [esi].p3_flags,PF_LVS ;lv values here?
  124. jz no_clip_lv ;..nope
  125. clip_value p3_l
  126. or [ebp].p3_flags,PF_LVS ;new point has lv set
  127. no_clip_lv:
  128. pop ecx ;get plane back
  129. ;negate z if clipping against left or bot
  130. test cl,CC_OFF_LEFT+CC_OFF_BOT ;right or top (neg)?
  131. jz not_neg2
  132. neg [ebp].z ;z=-x (or -y)
  133. not_neg2:
  134. ;see if discarded point is temp point, and free it if so
  135. mov edi,ebp ;return correct point
  136. mov eax,edi
  137. jmp code_point ;returns bl=codes
  138. ;clips a line to the viewing pyramid.
  139. ;takes esi,edi=points (pointers), al=codes_or
  140. ;return esi,edi=clipped points, one or both new
  141. clip_line: pushm ebx,ecx,edx,ebp
  142. mov ecx,1 ;plane flag
  143. l_plane_loop: test al,cl ;off this plane?
  144. jz l_not_this_plane
  145. test [esi].p3_codes,cl ;this one on?
  146. jz order_ok ;..yep
  147. xchg esi,edi ;..nope
  148. order_ok:
  149. push edi ;save old off-screen point
  150. call clip_edge ;esi=on, edi=off
  151. ;returns bl=new edi codes
  152. pop eax ;get discarded point
  153. ;see if must free rejected point
  154. test [eax].p3_flags,PF_TEMP_POINT
  155. jz not_temp_eax
  156. xchg esi,eax
  157. call free_temp_point
  158. mov esi,eax
  159. not_temp_eax:
  160. mov al,[esi].p3_codes ;get esi codes
  161. test al,bl ;clipped away?
  162. jnz l_clipped_away ;..yep
  163. or al,bl ;get new codes_or
  164. l_not_this_plane:
  165. add ecx,ecx ;next plane
  166. cmp ecx,16 ;done?
  167. jne l_plane_loop ;..nope
  168. l_clipped_away: popm ebx,ecx,edx,ebp
  169. ret
  170. ;TEMPORARY - inline this code when working
  171. ;takes esi,edi=lists
  172. ;returns edi=end of new list, dx=new codes. trashes eax,ebx,edx,ebp,esi
  173. clip_plane:
  174. mov ebx,nverts
  175. ;copy first two verts to end
  176. mov eax,[esi]
  177. mov [esi+ebx*4],eax
  178. mov eax,4[esi]
  179. mov 4[esi+ebx*4],eax
  180. mov nv_cnt,ebx ;loop variable
  181. add esi,4 ;point at second
  182. mov edx,0ff00h ;initialize codes
  183. point_loop: mov eax,[esi] ;get current point
  184. add esi,4
  185. ;go though list of points.
  186. test [eax].p3_codes,cl ;cur point off?
  187. jz cur_not_off ;..nope
  188. ;cur point is off. check prev and next
  189. mov ebx,[esi-8] ;get prev
  190. test [ebx].p3_codes,cl ;prev off?
  191. jnz prev_off ;..yup, so nothing to clip
  192. push eax ;save current point
  193. ;must clip cur (off screen) to prev (on screen)
  194. pushm edx,esi,edi ;save codes,list pointers
  195. mov esi,ebx ;esi=on screen
  196. mov edi,eax ;edi=off screen
  197. call clip_edge
  198. mov eax,edi ;save new point
  199. popm edx,esi,edi ;get codes,list pointers
  200. mov [edi],eax ;store in dest list
  201. add edi,4
  202. or dl,bl ;update codes_or
  203. and dh,bl ;update codes_and
  204. pop eax ;restore current point
  205. prev_off:
  206. mov ebx,[esi] ;get next
  207. test [ebx].p3_codes,cl ;next off?
  208. jnz next_off ;..yes
  209. push eax ;save current point
  210. ;must clip cur (off screen) to next (on screen)
  211. pushm edx,esi,edi ;save codes,list pointers
  212. mov esi,ebx ;esi=on screen
  213. mov edi,eax ;edi=off screen
  214. call clip_edge
  215. mov eax,edi ;save new point
  216. popm edx,esi,edi ;get codes,list pointers
  217. mov [edi],eax ;store in dest list
  218. add edi,4
  219. or dl,bl ;update codes_or
  220. and dh,bl ;update codes_and
  221. pop eax ;get current back
  222. next_off:
  223. ;see if must free discarded point
  224. test [eax].p3_flags,PF_TEMP_POINT
  225. jz not_temp
  226. xchg esi,eax
  227. call free_temp_point
  228. mov esi,eax
  229. not_temp:
  230. jmp do_next_point
  231. cur_not_off: mov [edi],eax ;store cur in dest buffer
  232. add edi,4
  233. or dl,[eax].p3_codes ;update codes_or
  234. and dh,[eax].p3_codes ;update codes_and
  235. do_next_point: dec nv_cnt
  236. jnz point_loop
  237. ret
  238. ;3d clip a polygon.
  239. ;takes esi=src list, edi=dest list, ecx=nverts, al=codes_or
  240. ;returns esi=list of clipped points, some of them new, ecx=new nverts, dx=codes
  241. ;esi at exit will be either of esi,edi at entry
  242. clip_polygon: push ebp
  243. mov nverts,ecx ;save
  244. ;now loop through each plane, a-clipping as we go
  245. mov ecx,1 ;plane flag
  246. mov dl,al ;dl = codes_or
  247. ;clipping from [esi] -> [edi]
  248. p_plane_loop: test dl,cl ;off this plane?
  249. jz p_not_this_plane
  250. push esi ;save src ptr
  251. push edi ;save dest ptr
  252. ;clip against this plane
  253. call clip_plane ;when working, inline this code
  254. ;done clip for this plane
  255. mov eax,edi ;end of dest loop
  256. pop esi ;get start of dest buffer
  257. sub eax,esi ;get delta
  258. sar eax,2 ;get new vert count
  259. mov nverts,eax ;save new value
  260. pop edi ;new dest = old scr
  261. test dh,dh ;check new codes_and
  262. jnz p_clipped_away ;polygon all off screen
  263. p_not_this_plane: add ecx,ecx ;next plane
  264. cmp ecx,16 ;done?
  265. jne p_plane_loop ;..nope
  266. p_clipped_away: pop ebp
  267. mov ecx,nverts ;new value
  268. ret
  269. _TEXT ends
  270. ;should I write a combined clipper/projector?
  271. end