clip.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. //---------------------------------------------------------------------------------------------------
  5. // Screen Clip code for use with video cards without guard bands and BLADE.
  6. //
  7. // Generally, we will only need one or two of the below routines per triangle.
  8. //
  9. // If a triangle is completely on screen, none of the below should be called.
  10. //
  11. // Each triangle can be easily checked to see which of the below should be
  12. // called in its case. An easy, low-end machine optimization would be to
  13. // NOT call any of the below for TGL/MSL shapes which are partly off screen
  14. // and simply not to draw the shape. Profiling will indicate if this is
  15. // necessary.
  16. //
  17. // Color space clipping is HUGELY painful and we are cheating until it
  18. // becomes necessary to do otherwise.
  19. //
  20. // Triangles will be converted into polygons with as many as five sides.
  21. // It will be necessary in the draw code to hand the vertices down to
  22. // GOS/BLADE in triangles to avoid any weirdness in their code!
  23. //
  24. // These routines are easily optimized and assembled if and when it becomes
  25. // necessary to do so. Routines should be inlined for speed!
  26. //---------------------------------------------------------------------------------------------------
  27. #ifndef CLIP_H
  28. #define CLIP_H
  29. #include <gameos.hpp>
  30. //---------------------------------------------------------------------------------------------------
  31. inline void xLeftEdgeclip (gos_VERTEX *vertices, long &numVertices, float leftEdge)
  32. {
  33. //------------------------------------------
  34. //make local copy of all point data involved
  35. gos_VERTEX points[6];
  36. memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
  37. //------------------------------------------
  38. long first = numVertices-1;
  39. long second = 0;
  40. //----------------------------------------------
  41. // Index to current vertex in clipped polygon.
  42. //----------------------------------------------
  43. long work = 0;
  44. //------------------------------
  45. //final number of polygon points
  46. //------------------------------
  47. long n_points= 0;
  48. //----------------------------
  49. //process points in edge order
  50. //----------------------------
  51. for (long s=0; s<numVertices; s++, second++)
  52. {
  53. float clipEdgeTest = points[first].x;
  54. //----------------------------------------------------------------
  55. // if this point is not beyond the clipping Edge, store it.
  56. //----------------------------------------------------------------
  57. if (clipEdgeTest >= leftEdge)
  58. {
  59. //------------------------------------------------------------
  60. gos_VERTEX* workv = &(vertices[work]);
  61. memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
  62. //------------------------------------------------------------
  63. work++;
  64. n_points++;
  65. }
  66. //------------------------------------------------------------
  67. //if the line defined by first and second intersects the
  68. //clipping plane, generate a new point and calculate its info.
  69. //------------------------------------------------------------
  70. if (((clipEdgeTest < leftEdge) && (points[second].x >= leftEdge)) ||
  71. ((clipEdgeTest >= leftEdge) && (points[second].x < leftEdge)))
  72. {
  73. gos_VERTEX* workv = &(vertices[work]);
  74. float sry = points[second].y;
  75. float srx = points[second].x;
  76. float srz = points[second].z;
  77. float srw = points[second].rhw;
  78. float sru = points[second].u;
  79. float srv = points[second].v;
  80. float fry = points[first].y;
  81. float frx = points[first].x;
  82. float frz = points[first].z;
  83. float frw = points[first].rhw;
  84. float fru = points[first].u;
  85. float frv = points[first].v;
  86. float mu = (leftEdge - srx)/(frx - srx);
  87. workv->x = leftEdge;
  88. workv->y = ((fry - sry) * mu) + sry;
  89. workv->z = ((frz - srz) * mu) + srz;
  90. // Clipping color is HUGELY painful at this point. Try cheating first!
  91. if (clipEdgeTest < leftEdge)
  92. {
  93. workv->argb = points[first].argb;
  94. workv->frgb = points[first].frgb;
  95. }
  96. else
  97. {
  98. workv->argb = points[second].argb;
  99. workv->frgb = points[second].frgb;
  100. }
  101. workv->rhw = ((frw - srw) * mu) + srw;
  102. workv->u = ((fru - sru) * mu) + sru;
  103. workv->v = ((frv - srv) * mu) + srv;
  104. work++;
  105. n_points++;
  106. }
  107. first = second;
  108. }
  109. numVertices = n_points;
  110. }
  111. //---------------------------------------------------------------------------------------------------
  112. inline void xRightEdgeclip (gos_VERTEX *vertices, long &numVertices, float rightEdge)
  113. {
  114. //------------------------------------------
  115. //make local copy of all point data involved
  116. gos_VERTEX points[6];
  117. memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
  118. //------------------------------------------
  119. long first = numVertices-1;
  120. long second = 0;
  121. //----------------------------------------------
  122. // Index to current vertex in clipped polygon.
  123. //----------------------------------------------
  124. long work = 0;
  125. //------------------------------
  126. //final number of polygon points
  127. //------------------------------
  128. long n_points= 0;
  129. //----------------------------
  130. //process points in edge order
  131. //----------------------------
  132. for (long s=0; s<numVertices; s++, second++)
  133. {
  134. float clipEdgeTest = points[first].x;
  135. //----------------------------------------------------------------
  136. // if this point is not beyond the clipping Edge, store it.
  137. //----------------------------------------------------------------
  138. if (clipEdgeTest < rightEdge)
  139. {
  140. //------------------------------------------------------------
  141. gos_VERTEX* workv = &(vertices[work]);
  142. memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
  143. //------------------------------------------------------------
  144. work++;
  145. n_points++;
  146. }
  147. //------------------------------------------------------------
  148. //if the line defined by first and second intersects the
  149. //clipping plane, generate a new point and calculate its info.
  150. //------------------------------------------------------------
  151. if (((clipEdgeTest >= rightEdge) && (points[second].x < rightEdge)) ||
  152. ((clipEdgeTest < rightEdge) && (points[second].x >= rightEdge)))
  153. {
  154. gos_VERTEX* workv = &(vertices[work]);
  155. float sry = points[second].y;
  156. float srx = points[second].x;
  157. float srz = points[second].z;
  158. float srw = points[second].rhw;
  159. float sru = points[second].u;
  160. float srv = points[second].v;
  161. float fry = points[first].y;
  162. float frx = points[first].x;
  163. float frz = points[first].z;
  164. float frw = points[first].rhw;
  165. float fru = points[first].u;
  166. float frv = points[first].v;
  167. float mu = (rightEdge - srx)/(frx - srx);
  168. workv->x = rightEdge - 1.0f;
  169. workv->y = ((fry - sry) * mu) + sry;
  170. workv->z = ((frz - srz) * mu) + srz;
  171. // Clipping color is HUGELY painful at this point. Try cheating first!
  172. if (clipEdgeTest >= rightEdge)
  173. {
  174. workv->argb = points[first].argb;
  175. workv->frgb = points[first].frgb;
  176. }
  177. else
  178. {
  179. workv->argb = points[second].argb;
  180. workv->frgb = points[second].frgb;
  181. }
  182. workv->rhw = ((frw - srw) * mu) + srw;
  183. workv->u = ((fru - sru) * mu) + sru;
  184. workv->v = ((frv - srv) * mu) + srv;
  185. work++;
  186. n_points++;
  187. }
  188. first = second;
  189. }
  190. numVertices = n_points;
  191. }
  192. //---------------------------------------------------------------------------------------------------
  193. inline void yTopEdgeclip (gos_VERTEX *vertices, long &numVertices, float topEdge)
  194. {
  195. //------------------------------------------
  196. //make local copy of all point data involved
  197. gos_VERTEX points[6];
  198. memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
  199. //------------------------------------------
  200. long first = numVertices-1;
  201. long second = 0;
  202. //----------------------------------------------
  203. // Index to current vertex in clipped polygon.
  204. //----------------------------------------------
  205. long work = 0;
  206. //------------------------------
  207. //final number of polygon points
  208. //------------------------------
  209. long n_points= 0;
  210. //----------------------------
  211. //process points in edge order
  212. //----------------------------
  213. for (long s=0; s<numVertices; s++, second++)
  214. {
  215. float clipEdgeTest = points[first].y;
  216. //----------------------------------------------------------------
  217. // if this point is not beyond the clipping Edge, store it.
  218. //----------------------------------------------------------------
  219. if (clipEdgeTest >= topEdge)
  220. {
  221. //------------------------------------------------------------
  222. gos_VERTEX* workv = &(vertices[work]);
  223. memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
  224. //------------------------------------------------------------
  225. work++;
  226. n_points++;
  227. }
  228. //------------------------------------------------------------
  229. //if the line defined by first and second intersects the
  230. //clipping plane, generate a new point and calculate its info.
  231. //------------------------------------------------------------
  232. if (((clipEdgeTest < topEdge) && (points[second].y >= topEdge)) ||
  233. ((clipEdgeTest >= topEdge) && (points[second].y < topEdge)))
  234. {
  235. gos_VERTEX* workv = &(vertices[work]);
  236. float sry = points[second].y;
  237. float srx = points[second].x;
  238. float srz = points[second].z;
  239. float srw = points[second].rhw;
  240. float sru = points[second].u;
  241. float srv = points[second].v;
  242. float fry = points[first].y;
  243. float frx = points[first].x;
  244. float frz = points[first].z;
  245. float frw = points[first].rhw;
  246. float fru = points[first].u;
  247. float frv = points[first].v;
  248. float mu = (topEdge - sry)/(fry - sry);
  249. workv->y = topEdge;
  250. workv->x = ((frx - srx) * mu) + srx;
  251. workv->z = ((frz - srz) * mu) + srz;
  252. // Clipping color is HUGELY painful at this point. Try cheating first!
  253. if (clipEdgeTest < topEdge)
  254. {
  255. workv->argb = points[first].argb;
  256. workv->frgb = points[first].frgb;
  257. }
  258. else
  259. {
  260. workv->argb = points[second].argb;
  261. workv->frgb = points[second].frgb;
  262. }
  263. workv->rhw = ((frw - srw) * mu) + srw;
  264. workv->u = ((fru - sru) * mu) + sru;
  265. workv->v = ((frv - srv) * mu) + srv;
  266. work++;
  267. n_points++;
  268. }
  269. first = second;
  270. }
  271. numVertices = n_points;
  272. }
  273. //---------------------------------------------------------------------------------------------------
  274. inline void yBottomEdgeclip (gos_VERTEX *vertices, long &numVertices, float bottomEdge)
  275. {
  276. //------------------------------------------
  277. //make local copy of all point data involved
  278. gos_VERTEX points[6];
  279. memcpy(points,vertices,sizeof(gos_VERTEX)*numVertices);
  280. //------------------------------------------
  281. long first = numVertices-1;
  282. long second = 0;
  283. //----------------------------------------------
  284. // Index to current vertex in clipped polygon.
  285. //----------------------------------------------
  286. long work = 0;
  287. //------------------------------
  288. //final number of polygon points
  289. //------------------------------
  290. long n_points= 0;
  291. //----------------------------
  292. //process points in edge order
  293. //----------------------------
  294. for (long s=0; s<numVertices; s++, second++)
  295. {
  296. float clipEdgeTest = points[first].y;
  297. //----------------------------------------------------------------
  298. // if this point is not beyond the clipping Edge, store it.
  299. //----------------------------------------------------------------
  300. if (clipEdgeTest < bottomEdge)
  301. {
  302. //------------------------------------------------------------
  303. gos_VERTEX* workv = &(vertices[work]);
  304. memcpy(workv,&(points[first]),sizeof(gos_VERTEX));
  305. //------------------------------------------------------------
  306. work++;
  307. n_points++;
  308. }
  309. //------------------------------------------------------------
  310. //if the line defined by first and second intersects the
  311. //clipping plane, generate a new point and calculate its info.
  312. //------------------------------------------------------------
  313. if (((clipEdgeTest >= bottomEdge) && (points[second].y < bottomEdge)) ||
  314. ((clipEdgeTest < bottomEdge) && (points[second].y >= bottomEdge)))
  315. {
  316. gos_VERTEX* workv = &(vertices[work]);
  317. float sry = points[second].y;
  318. float srx = points[second].x;
  319. float srz = points[second].z;
  320. float srw = points[second].rhw;
  321. float sru = points[second].u;
  322. float srv = points[second].v;
  323. float fry = points[first].y;
  324. float frx = points[first].x;
  325. float frz = points[first].z;
  326. float frw = points[first].rhw;
  327. float fru = points[first].u;
  328. float frv = points[first].v;
  329. float mu = (bottomEdge - sry)/(fry - sry);
  330. workv->y = bottomEdge - 1.0f;
  331. workv->x = ((frx - srx) * mu) + srx;
  332. workv->z = ((frz - srz) * mu) + srz;
  333. // Clipping color is HUGELY painful at this point. Try cheating first!
  334. if (clipEdgeTest >= bottomEdge)
  335. {
  336. workv->argb = points[first].argb;
  337. workv->frgb = points[first].frgb;
  338. }
  339. else
  340. {
  341. workv->argb = points[second].argb;
  342. workv->frgb = points[second].frgb;
  343. }
  344. workv->rhw = ((frw - srw) * mu) + srw;
  345. workv->u = ((fru - sru) * mu) + sru;
  346. workv->v = ((frv - srv) * mu) + srv;
  347. work++;
  348. n_points++;
  349. }
  350. first = second;
  351. }
  352. numVertices = n_points;
  353. }
  354. //---------------------------------------------------------------------------------------------------
  355. #endif