CLIPPER.ASM 8.7 KB

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