sgUtil.cpp

Engine/source/scene/sgUtil.cpp

More...

Public Functions

bool
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.

sgOrientClipPlanes(PlaneF * planes, const Point3F & camPos, const Point3F & leftUp, const Point3F & leftDown, const Point3F & rightUp, const Point3F & rightDown)

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