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