sgUtil.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "scene/sgUtil.h"
  23. #include "math/mRect.h"
  24. #include "math/mMatrix.h"
  25. #include "math/mPlane.h"
  26. namespace {
  27. // Static state for sgComputeNewFrustum
  28. //
  29. Point3F sgCamPoint;
  30. MatrixF sgWSToOSMatrix;
  31. MatrixF sgProjMatrix;
  32. PlaneF sgOSPlaneFar;
  33. PlaneF sgOSPlaneXMin;
  34. PlaneF sgOSPlaneXMax;
  35. PlaneF sgOSPlaneYMin;
  36. PlaneF sgOSPlaneYMax;
  37. void clipToPlane(Point3F* points, U32& rNumPoints, const PlaneF& rPlane)
  38. {
  39. S32 start = -1;
  40. for (U32 i = 0; i < rNumPoints; i++) {
  41. if (rPlane.whichSide(points[i]) == PlaneF::Front) {
  42. start = i;
  43. break;
  44. }
  45. }
  46. // Nothing was in front of the plane...
  47. if (start == -1) {
  48. rNumPoints = 0;
  49. return;
  50. }
  51. Point3F finalPoints[128];
  52. U32 numFinalPoints = 0;
  53. U32 baseStart = start;
  54. U32 end = (start + 1) % rNumPoints;
  55. while (end != baseStart) {
  56. const Point3F& rStartPoint = points[start];
  57. const Point3F& rEndPoint = points[end];
  58. PlaneF::Side fSide = rPlane.whichSide(rStartPoint);
  59. PlaneF::Side eSide = rPlane.whichSide(rEndPoint);
  60. S32 code = fSide * 3 + eSide;
  61. switch (code) {
  62. case 4: // f f
  63. case 3: // f o
  64. case 1: // o f
  65. case 0: // o o
  66. // No Clipping required
  67. finalPoints[numFinalPoints++] = points[start];
  68. start = end;
  69. end = (end + 1) % rNumPoints;
  70. break;
  71. case 2: { // f b
  72. // In this case, we emit the front point, Insert the intersection,
  73. // and advancing to point to first point that is in front or on...
  74. //
  75. finalPoints[numFinalPoints++] = points[start];
  76. Point3F vector = rEndPoint - rStartPoint;
  77. F32 t = -(rPlane.distToPlane(rStartPoint) / mDot(rPlane, vector));
  78. Point3F intersection = rStartPoint + (vector * t);
  79. finalPoints[numFinalPoints++] = intersection;
  80. U32 endSeek = (end + 1) % rNumPoints;
  81. while (rPlane.whichSide(points[endSeek]) == PlaneF::Back)
  82. endSeek = (endSeek + 1) % rNumPoints;
  83. end = endSeek;
  84. start = (end + (rNumPoints - 1)) % rNumPoints;
  85. const Point3F& rNewStartPoint = points[start];
  86. const Point3F& rNewEndPoint = points[end];
  87. vector = rNewEndPoint - rNewStartPoint;
  88. t = -(rPlane.distToPlane(rNewStartPoint) / mDot(rPlane, vector));
  89. intersection = rNewStartPoint + (vector * t);
  90. points[start] = intersection;
  91. }
  92. break;
  93. case -1: {// o b
  94. // In this case, we emit the front point, and advance to point to first
  95. // point that is in front or on...
  96. //
  97. finalPoints[numFinalPoints++] = points[start];
  98. U32 endSeek = (end + 1) % rNumPoints;
  99. while (rPlane.whichSide(points[endSeek]) == PlaneF::Back)
  100. endSeek = (endSeek + 1) % rNumPoints;
  101. end = endSeek;
  102. start = (end + (rNumPoints - 1)) % rNumPoints;
  103. const Point3F& rNewStartPoint = points[start];
  104. const Point3F& rNewEndPoint = points[end];
  105. Point3F vector = rNewEndPoint - rNewStartPoint;
  106. F32 t = -(rPlane.distToPlane(rNewStartPoint) / mDot(rPlane, vector));
  107. Point3F intersection = rNewStartPoint + (vector * t);
  108. points[start] = intersection;
  109. }
  110. break;
  111. case -2: // b f
  112. case -3: // b o
  113. case -4: // b b
  114. // In the algorithm used here, this should never happen...
  115. AssertISV(false, "SGUtil::clipToPlane: error in polygon clipper");
  116. break;
  117. default:
  118. AssertFatal(false, "SGUtil::clipToPlane: bad outcode");
  119. break;
  120. }
  121. }
  122. // Emit the last point.
  123. finalPoints[numFinalPoints++] = points[start];
  124. AssertFatal(numFinalPoints >= 3, avar("Error, this shouldn't happen! Invalid winding in clipToPlane: %d", numFinalPoints));
  125. // Copy the new rWinding, and we're set!
  126. //
  127. dMemcpy(points, finalPoints, numFinalPoints * sizeof(Point3F));
  128. rNumPoints = numFinalPoints;
  129. AssertISV(rNumPoints <= 128, "MaxWindingPoints exceeded in scenegraph. Fatal error.");
  130. }
  131. void fixupViewport(const F64* oldFrustum,
  132. const RectI& oldViewport,
  133. F64* newFrustum,
  134. RectI& newViewport)
  135. {
  136. F64 widthV = newFrustum[1] - newFrustum[0];
  137. F64 heightV = newFrustum[3] - newFrustum[2];
  138. F64 fx0 = (newFrustum[0] - oldFrustum[0]) / (oldFrustum[1] - oldFrustum[0]);
  139. F64 fx1 = (oldFrustum[1] - newFrustum[1]) / (oldFrustum[1] - oldFrustum[0]);
  140. F64 dV0 = F64(oldViewport.point.x) + fx0 * F64(oldViewport.extent.x);
  141. F64 dV1 = F64(oldViewport.point.x +
  142. oldViewport.extent.x) - fx1 * F64(oldViewport.extent.x);
  143. F64 fdV0 = mFloor(dV0);
  144. F64 cdV1 = mCeil(dV1);
  145. F64 new0 = newFrustum[0] - ((dV0 - fdV0) * (widthV / F64(oldViewport.extent.x)));
  146. F64 new1 = newFrustum[1] + ((cdV1 - dV1) * (widthV / F64(oldViewport.extent.x)));
  147. newFrustum[0] = new0;
  148. newFrustum[1] = new1;
  149. newViewport.point.x = S32(fdV0);
  150. newViewport.extent.x = S32(cdV1) - newViewport.point.x;
  151. F64 fy0 = (oldFrustum[3] - newFrustum[3]) / (oldFrustum[3] - oldFrustum[2]);
  152. F64 fy1 = (newFrustum[2] - oldFrustum[2]) / (oldFrustum[3] - oldFrustum[2]);
  153. dV0 = F64(oldViewport.point.y) + fy0 * F64(oldViewport.extent.y);
  154. dV1 = F64(oldViewport.point.y + oldViewport.extent.y) - fy1 * F64(oldViewport.extent.y);
  155. fdV0 = mFloor(dV0);
  156. cdV1 = mCeil(dV1);
  157. new0 = newFrustum[2] - ((cdV1 - dV1) * (heightV / F64(oldViewport.extent.y)));
  158. new1 = newFrustum[3] + ((dV0 - fdV0) * (heightV / F64(oldViewport.extent.y)));
  159. newFrustum[2] = new0;
  160. newFrustum[3] = new1;
  161. newViewport.point.y = S32(fdV0);
  162. newViewport.extent.y = S32(cdV1) - newViewport.point.y;
  163. }
  164. bool projectClipAndBoundWinding(const SGWinding& rWinding, F64* pResult)
  165. {
  166. AssertFatal(rWinding.numPoints >= 3, "Error, that's not a winding!");
  167. static Point3F windingPoints[128];
  168. U32 i;
  169. for (i = 0; i < rWinding.numPoints; i++)
  170. windingPoints[i] = rWinding.points[i];
  171. U32 numPoints = rWinding.numPoints;
  172. clipToPlane(windingPoints, numPoints, sgOSPlaneFar);
  173. if (numPoints != 0)
  174. clipToPlane(windingPoints, numPoints, sgOSPlaneXMin);
  175. if (numPoints != 0)
  176. clipToPlane(windingPoints, numPoints, sgOSPlaneXMax);
  177. if (numPoints != 0)
  178. clipToPlane(windingPoints, numPoints, sgOSPlaneYMin);
  179. if (numPoints != 0)
  180. clipToPlane(windingPoints, numPoints, sgOSPlaneYMax);
  181. if (numPoints == 0)
  182. return false;
  183. Point4F projPoint;
  184. for (i = 0; i < numPoints; i++) {
  185. projPoint.set(windingPoints[i].x, windingPoints[i].y, windingPoints[i].z, 1.0);
  186. sgProjMatrix.mul(projPoint);
  187. AssertFatal(projPoint.w != 0.0, "Error, that's bad! (Point projected with non-zero w.)");
  188. projPoint.x /= projPoint.w;
  189. projPoint.y /= projPoint.w;
  190. if (projPoint.x < pResult[0])
  191. pResult[0] = projPoint.x;
  192. if (projPoint.x > pResult[1])
  193. pResult[1] = projPoint.x;
  194. if (projPoint.y < pResult[2])
  195. pResult[2] = projPoint.y;
  196. if (projPoint.y > pResult[3])
  197. pResult[3] = projPoint.y;
  198. }
  199. if (pResult[0] < -1.0f) pResult[0] = -1.0f;
  200. if (pResult[2] < -1.0f) pResult[2] = -1.0f;
  201. if (pResult[1] > 1.0f) pResult[1] = 1.0f;
  202. if (pResult[3] > 1.0f) pResult[3] = 1.0f;
  203. return true;
  204. }
  205. } // namespace { }
  206. //--------------------------------------------------------------------------
  207. bool sgComputeNewFrustum(const Frustum &oldFrustum,
  208. const F64 nearPlane,
  209. const F64 farPlane,
  210. const RectI& oldViewport,
  211. const SGWinding* windings,
  212. const U32 numWindings,
  213. const MatrixF& modelview,
  214. F64 *newFrustum,
  215. RectI& newViewport,
  216. const bool flippedMatrix)
  217. {
  218. return false;
  219. }
  220. void sgComputeOSFrustumPlanes(const F64 frustumParameters[6],
  221. const MatrixF& worldSpaceToObjectSpace,
  222. const Point3F& wsCamPoint,
  223. PlaneF& outFarPlane,
  224. PlaneF& outXMinPlane,
  225. PlaneF& outXMaxPlane,
  226. PlaneF& outYMinPlane,
  227. PlaneF& outYMaxPlane)
  228. {
  229. // Create the object space clipping planes...
  230. Point3F ul(frustumParameters[0] * 1000.0, frustumParameters[4] * 1000.0, frustumParameters[3] * 1000.0);
  231. Point3F ur(frustumParameters[1] * 1000.0, frustumParameters[4] * 1000.0, frustumParameters[3] * 1000.0);
  232. Point3F ll(frustumParameters[0] * 1000.0, frustumParameters[4] * 1000.0, frustumParameters[2] * 1000.0);
  233. Point3F lr(frustumParameters[1] * 1000.0, frustumParameters[4] * 1000.0, frustumParameters[2] * 1000.0);
  234. Point3F farPlane(0, frustumParameters[5], 0);
  235. worldSpaceToObjectSpace.mulP(ul);
  236. worldSpaceToObjectSpace.mulP(ur);
  237. worldSpaceToObjectSpace.mulP(ll);
  238. worldSpaceToObjectSpace.mulP(lr);
  239. worldSpaceToObjectSpace.mulP(farPlane);
  240. outFarPlane.set(farPlane, wsCamPoint - farPlane);
  241. outXMinPlane.set(wsCamPoint, ul, ll);
  242. outXMaxPlane.set(wsCamPoint, lr, ur);
  243. outYMinPlane.set(wsCamPoint, ur, ul);
  244. outYMaxPlane.set(wsCamPoint, ll, lr);
  245. }
  246. // MM/JF: Added for mirrorSubObject fix.
  247. void sgOrientClipPlanes(
  248. PlaneF * planes,
  249. const Point3F & camPos,
  250. const Point3F & leftUp,
  251. const Point3F & leftDown,
  252. const Point3F & rightUp,
  253. const Point3F & rightDown)
  254. {
  255. AssertFatal(planes, "orientClipPlanes: NULL planes ptr");
  256. planes[0].set(camPos, leftUp, leftDown);
  257. planes[1].set(camPos, rightUp, leftUp);
  258. planes[2].set(camPos, rightDown, rightUp);
  259. planes[3].set(camPos, leftDown, rightDown);
  260. planes[4].set(leftUp, rightUp, rightDown);
  261. // clip-planes through mirror portal are inverted
  262. PlaneF plane(leftUp, rightUp, rightDown);
  263. if(plane.whichSide(camPos) == PlaneF::Back)
  264. for(U32 i = 0; i < 5; i++)
  265. planes[i].invert();
  266. }