CLIP.C 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /******************************************************************************
  2. Plush Version 1.2
  3. clip.c
  4. 3D Frustum Clipping
  5. Copyright (c) 1996-2000, Justin Frankel
  6. ******************************************************************************/
  7. #include "plush.h"
  8. #define NUM_CLIP_PLANES 5
  9. typedef struct
  10. {
  11. pl_Vertex newVertices[8];
  12. double Shades[8];
  13. double MappingU[8];
  14. double MappingV[8];
  15. double eMappingU[8];
  16. double eMappingV[8];
  17. } _clipInfo;
  18. static _clipInfo m_cl[2];
  19. static double m_clipPlanes[NUM_CLIP_PLANES][4];
  20. static pl_Cam *m_cam;
  21. static pl_sInt32 m_cx, m_cy;
  22. static double m_fov;
  23. static double m_adj_asp;
  24. static void _FindNormal(double x2, double x3,
  25. double y2, double y3,
  26. double zv,
  27. double *res);
  28. /* Returns: 0 if nothing gets in, 1 or 2 if pout1 & pout2 get in */
  29. static pl_uInt _ClipToPlane(pl_uInt numVerts, double *plane);
  30. void plClipSetFrustum(pl_Cam *cam) {
  31. m_adj_asp = 1.0 / cam->AspectRatio;
  32. m_fov = plMin(plMax(cam->Fov,1.0),179.0);
  33. m_fov = (1.0/tan(m_fov*(PL_PI/360.0)))*(double) (cam->ClipRight-cam->ClipLeft);
  34. m_cx = cam->CenterX<<20;
  35. m_cy = cam->CenterY<<20;
  36. m_cam = cam;
  37. memset(m_clipPlanes,0,sizeof(m_clipPlanes));
  38. /* Back */
  39. m_clipPlanes[0][2] = -1.0;
  40. m_clipPlanes[0][3] = -cam->ClipBack;
  41. /* Left */
  42. m_clipPlanes[1][3] = 0.00000001;
  43. if (cam->ClipLeft == cam->CenterX) {
  44. m_clipPlanes[1][0] = 1.0;
  45. }
  46. else _FindNormal(-100,-100,
  47. 100, -100,
  48. m_fov*-100.0/(cam->ClipLeft-cam->CenterX),
  49. m_clipPlanes[1]);
  50. if (cam->ClipLeft > cam->CenterX) {
  51. m_clipPlanes[1][0] = -m_clipPlanes[1][0];
  52. m_clipPlanes[1][1] = -m_clipPlanes[1][1];
  53. m_clipPlanes[1][2] = -m_clipPlanes[1][2];
  54. }
  55. /* Right */
  56. m_clipPlanes[2][3] = 0.00000001;
  57. if (cam->ClipRight == cam->CenterX) {
  58. m_clipPlanes[2][0] = -1.0;
  59. }
  60. else _FindNormal(100,100,
  61. -100, 100,
  62. m_fov*100.0/(cam->ClipRight-cam->CenterX),
  63. m_clipPlanes[2]);
  64. if (cam->ClipRight < cam->CenterX) {
  65. m_clipPlanes[2][0] = -m_clipPlanes[2][0];
  66. m_clipPlanes[2][1] = -m_clipPlanes[2][1];
  67. m_clipPlanes[2][2] = -m_clipPlanes[2][2];
  68. }
  69. /* Top */
  70. m_clipPlanes[3][3] = 0.00000001;
  71. if (cam->ClipTop == cam->CenterY) {
  72. m_clipPlanes[3][1] = -1.0;
  73. } else _FindNormal(100, -100,
  74. 100, 100,
  75. m_fov*m_adj_asp*100.0/(cam->CenterY-cam->ClipTop),
  76. m_clipPlanes[3]);
  77. if (cam->ClipTop > cam->CenterY) {
  78. m_clipPlanes[3][0] = -m_clipPlanes[3][0];
  79. m_clipPlanes[3][1] = -m_clipPlanes[3][1];
  80. m_clipPlanes[3][2] = -m_clipPlanes[3][2];
  81. }
  82. /* Bottom */
  83. m_clipPlanes[4][3] = 0.00000001;
  84. if (cam->ClipBottom == cam->CenterY) {
  85. m_clipPlanes[4][1] = 1.0;
  86. } else _FindNormal(-100, 100,
  87. -100, -100,
  88. m_fov*m_adj_asp*-100.0/(cam->CenterY-cam->ClipBottom),
  89. m_clipPlanes[4]);
  90. if (cam->ClipBottom < cam->CenterY) {
  91. m_clipPlanes[4][0] = -m_clipPlanes[4][0];
  92. m_clipPlanes[4][1] = -m_clipPlanes[4][1];
  93. m_clipPlanes[4][2] = -m_clipPlanes[4][2];
  94. }
  95. }
  96. void plClipRenderFace(pl_Face *face) {
  97. pl_uInt k, a, w, numVerts, q;
  98. double tmp, tmp2;
  99. pl_Face newface;
  100. for (a = 0; a < 3; a ++) {
  101. m_cl[0].newVertices[a] = *(face->Vertices[a]);
  102. m_cl[0].Shades[a] = face->Shades[a];
  103. m_cl[0].MappingU[a] = face->MappingU[a];
  104. m_cl[0].MappingV[a] = face->MappingV[a];
  105. m_cl[0].eMappingU[a] = face->eMappingU[a];
  106. m_cl[0].eMappingV[a] = face->eMappingV[a];
  107. }
  108. numVerts = 3;
  109. q = 0;
  110. a = (m_clipPlanes[0][3] < 0.0 ? 0 : 1);
  111. while (a < NUM_CLIP_PLANES && numVerts > 2)
  112. {
  113. numVerts = _ClipToPlane(numVerts, m_clipPlanes[a]);
  114. memcpy(&m_cl[0],&m_cl[1],sizeof(m_cl)/2);
  115. a++;
  116. }
  117. if (numVerts > 2) {
  118. memcpy(&newface,face,sizeof(pl_Face));
  119. for (k = 2; k < numVerts; k ++) {
  120. newface.fShade = plMax(0,plMin(face->fShade,1));
  121. for (a = 0; a < 3; a ++) {
  122. if (a == 0) w = 0;
  123. else w = a+(k-2);
  124. newface.Vertices[a] = m_cl[0].newVertices+w;
  125. newface.Shades[a] = (pl_Float) m_cl[0].Shades[w];
  126. newface.MappingU[a] = (pl_sInt32)m_cl[0].MappingU[w];
  127. newface.MappingV[a] = (pl_sInt32)m_cl[0].MappingV[w];
  128. newface.eMappingU[a] = (pl_sInt32)m_cl[0].eMappingU[w];
  129. newface.eMappingV[a] = (pl_sInt32)m_cl[0].eMappingV[w];
  130. newface.Scrz[a] = 1.0f/newface.Vertices[a]->xformedz;
  131. tmp2 = m_fov * newface.Scrz[a];
  132. tmp = tmp2*newface.Vertices[a]->xformedx;
  133. tmp2 *= newface.Vertices[a]->xformedy;
  134. newface.Scrx[a] = m_cx + ((pl_sInt32)((tmp*(float) (1<<20))));
  135. newface.Scry[a] = m_cy - ((pl_sInt32)((tmp2*m_adj_asp*(float) (1<<20))));
  136. }
  137. newface.Material->_PutFace(m_cam,&newface);
  138. plRender_TriStats[3] ++;
  139. }
  140. plRender_TriStats[2] ++;
  141. }
  142. }
  143. pl_sInt plClipNeeded(pl_Face *face) {
  144. double dr,dl,db,dt;
  145. double f;
  146. dr = (m_cam->ClipRight-m_cam->CenterX);
  147. dl = (m_cam->ClipLeft-m_cam->CenterX);
  148. db = (m_cam->ClipBottom-m_cam->CenterY);
  149. dt = (m_cam->ClipTop-m_cam->CenterY);
  150. f = m_fov*m_adj_asp;
  151. return ((m_cam->ClipBack <= 0.0 ||
  152. face->Vertices[0]->xformedz <= m_cam->ClipBack ||
  153. face->Vertices[1]->xformedz <= m_cam->ClipBack ||
  154. face->Vertices[2]->xformedz <= m_cam->ClipBack) &&
  155. (face->Vertices[0]->xformedz >= 0 ||
  156. face->Vertices[1]->xformedz >= 0 ||
  157. face->Vertices[2]->xformedz >= 0) &&
  158. (face->Vertices[0]->xformedx*m_fov<=dr*face->Vertices[0]->xformedz ||
  159. face->Vertices[1]->xformedx*m_fov<=dr*face->Vertices[1]->xformedz ||
  160. face->Vertices[2]->xformedx*m_fov<=dr*face->Vertices[2]->xformedz) &&
  161. (face->Vertices[0]->xformedx*m_fov>=dl*face->Vertices[0]->xformedz ||
  162. face->Vertices[1]->xformedx*m_fov>=dl*face->Vertices[1]->xformedz ||
  163. face->Vertices[2]->xformedx*m_fov>=dl*face->Vertices[2]->xformedz) &&
  164. (face->Vertices[0]->xformedy*f<=db*face->Vertices[0]->xformedz ||
  165. face->Vertices[1]->xformedy*f<=db*face->Vertices[1]->xformedz ||
  166. face->Vertices[2]->xformedy*f<=db*face->Vertices[2]->xformedz) &&
  167. (face->Vertices[0]->xformedy*f>=dt*face->Vertices[0]->xformedz ||
  168. face->Vertices[1]->xformedy*f>=dt*face->Vertices[1]->xformedz ||
  169. face->Vertices[2]->xformedy*f>=dt*face->Vertices[2]->xformedz));
  170. }
  171. static void _FindNormal(double x2, double x3,double y2, double y3,
  172. double zv, double *res) {
  173. res[0] = zv*(y2-y3);
  174. res[1] = zv*(x3-x2);
  175. res[2] = x2*y3 - y2*x3;
  176. }
  177. /* Returns: 0 if nothing gets in, 1 or 2 if pout1 & pout2 get in */
  178. static pl_uInt _ClipToPlane(pl_uInt numVerts, double *plane)
  179. {
  180. pl_uInt i, nextvert, curin, nextin;
  181. double curdot, nextdot, scale;
  182. pl_uInt invert, outvert;
  183. invert = 0;
  184. outvert = 0;
  185. curdot = m_cl[0].newVertices[0].xformedx*plane[0] +
  186. m_cl[0].newVertices[0].xformedy*plane[1] +
  187. m_cl[0].newVertices[0].xformedz*plane[2];
  188. curin = (curdot >= plane[3]);
  189. for (i=0 ; i < numVerts; i++) {
  190. nextvert = (i + 1) % numVerts;
  191. if (curin) {
  192. m_cl[1].Shades[outvert] = m_cl[0].Shades[invert];
  193. m_cl[1].MappingU[outvert] = m_cl[0].MappingU[invert];
  194. m_cl[1].MappingV[outvert] = m_cl[0].MappingV[invert];
  195. m_cl[1].eMappingU[outvert] = m_cl[0].eMappingU[invert];
  196. m_cl[1].eMappingV[outvert] = m_cl[0].eMappingV[invert];
  197. m_cl[1].newVertices[outvert++] = m_cl[0].newVertices[invert];
  198. }
  199. nextdot = m_cl[0].newVertices[nextvert].xformedx*plane[0] +
  200. m_cl[0].newVertices[nextvert].xformedy*plane[1] +
  201. m_cl[0].newVertices[nextvert].xformedz*plane[2];
  202. nextin = (nextdot >= plane[3]);
  203. if (curin != nextin) {
  204. scale = (plane[3] - curdot) / (nextdot - curdot);
  205. m_cl[1].newVertices[outvert].xformedx = (pl_Float) (m_cl[0].newVertices[invert].xformedx +
  206. (m_cl[0].newVertices[nextvert].xformedx - m_cl[0].newVertices[invert].xformedx)
  207. * scale);
  208. m_cl[1].newVertices[outvert].xformedy = (pl_Float) (m_cl[0].newVertices[invert].xformedy +
  209. (m_cl[0].newVertices[nextvert].xformedy - m_cl[0].newVertices[invert].xformedy)
  210. * scale);
  211. m_cl[1].newVertices[outvert].xformedz = (pl_Float) (m_cl[0].newVertices[invert].xformedz +
  212. (m_cl[0].newVertices[nextvert].xformedz - m_cl[0].newVertices[invert].xformedz)
  213. * scale);
  214. m_cl[1].Shades[outvert] = m_cl[0].Shades[invert] +
  215. (m_cl[0].Shades[nextvert] - m_cl[0].Shades[invert]) * scale;
  216. m_cl[1].MappingU[outvert] = m_cl[0].MappingU[invert] +
  217. (m_cl[0].MappingU[nextvert] - m_cl[0].MappingU[invert]) * scale;
  218. m_cl[1].MappingV[outvert] = m_cl[0].MappingV[invert] +
  219. (m_cl[0].MappingV[nextvert] - m_cl[0].MappingV[invert]) * scale;
  220. m_cl[1].eMappingU[outvert] = m_cl[0].eMappingU[invert] +
  221. (m_cl[0].eMappingU[nextvert] - m_cl[0].eMappingU[invert]) * scale;
  222. m_cl[1].eMappingV[outvert] = m_cl[0].eMappingV[invert] +
  223. (m_cl[0].eMappingV[nextvert] - m_cl[0].eMappingV[invert]) * scale;
  224. outvert++;
  225. }
  226. curdot = nextdot;
  227. curin = nextin;
  228. invert++;
  229. }
  230. return outvert;
  231. }