summaryrefslogtreecommitdiff
path: root/Runtime/Geometry/ComputionalGeometry.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Geometry/ComputionalGeometry.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Geometry/ComputionalGeometry.cpp')
-rw-r--r--Runtime/Geometry/ComputionalGeometry.cpp304
1 files changed, 304 insertions, 0 deletions
diff --git a/Runtime/Geometry/ComputionalGeometry.cpp b/Runtime/Geometry/ComputionalGeometry.cpp
new file mode 100644
index 0000000..5b979a5
--- /dev/null
+++ b/Runtime/Geometry/ComputionalGeometry.cpp
@@ -0,0 +1,304 @@
+#include "UnityPrefix.h"
+#include "ComputionalGeometry.h"
+#include "Runtime/Math/FloatConversion.h"
+#include "Runtime/Math/Vector2.h"
+#include "Plane.h"
+#include <cmath>
+
+float SignedTriangleArea2D (const Vector2f& a, const Vector2f& b, const Vector2f& c)
+{
+ float i01 = (b.x - a.x) * (b.y + a.y);
+ float i12 = (c.x - b.x) * (c.y + b.y);
+ float i20 = (a.x - c.x) * (a.y + c.y);
+
+ return (i01 + i12 + i20) * 0.5F;
+}
+
+float SignedTriangleArea2D (const Vector3f* v)
+{
+ float i01 = (v[1].x - v[0].x) * (v[1].y + v[0].y);
+ float i12 = (v[2].x - v[1].x) * (v[2].y + v[1].y);
+ float i20 = (v[0].x - v[2].x) * (v[0].y + v[2].y);
+
+ return (i01 + i12 + i20) * 0.5F;
+}
+
+float TriangleArea3D (const Vector3f& a, const Vector3f& b, const Vector3f& c)
+{
+ return Magnitude (CalcRawNormalFromTriangle (a, b, c)) * 0.5F;
+}
+
+
+float CalculateProjectedBoxArea2D (const Vector3f* v)
+{
+ float i01 = (v[1].x - v[0].x) * (v[1].y + v[0].y);
+ float i13 = (v[3].x - v[1].x) * (v[3].y + v[1].y);
+ float i20 = (v[0].x - v[2].x) * (v[0].y + v[2].y);
+ float i37 = (v[7].x - v[3].x) * (v[7].y + v[3].y);
+ float i62 = (v[2].x - v[6].x) * (v[2].y + v[6].y);
+ float i23 = (v[3].x - v[2].x) * (v[3].y + v[2].y);
+ float i45 = (v[5].x - v[4].x) * (v[5].y + v[4].y);
+ float i57 = (v[7].x - v[5].x) * (v[7].y + v[5].y);
+ float i76 = (v[6].x - v[7].x) * (v[6].y + v[7].y);
+ float i64 = (v[4].x - v[6].x) * (v[4].y + v[6].y);
+ float i15 = (v[5].x - v[1].x) * (v[5].y + v[1].y);
+ float i40 = (v[0].x - v[4].x) * (v[0].y + v[4].y);
+
+ float area
+ = Abs (
+ i01
+ + i13
+ - i23
+ + i20);
+
+ area += Abs (
+ i23
+ + i37
+ + i76
+ + i62);
+
+ area += Abs (
+ i45
+ + i57
+ + i76
+ + i64);
+
+ area += Abs (
+ i01
+ + i15
+ - i45
+ + i40);
+
+ area += Abs (
+ i15
+ + i57
+ - i37
+ - i13);
+
+ area += Abs (
+ - i40
+ - i64
+ + i62
+ + i20);
+
+ return area * 0.5F;
+}
+
+float CalculateBoxAreaRadialFrustum (
+ Vector3f* v,
+ float inFovy,
+ float inNear,
+ float inFar,
+ float inScreenHeight)
+{
+ UInt32 i;
+ double cotan, w, distance;
+ Vector3f projectedTriangle[8];
+
+ cotan = Deg2Rad (inFovy / 2.0F);
+ cotan = cos (cotan) / sin (cotan);
+
+ for (i=0;i<8;i++)
+ {
+ projectedTriangle[i] = v[i];
+ distance = Magnitude (projectedTriangle[i]);
+
+ w = (inFar + inNear) / (inFar - inNear) * distance
+ + 2.0F * inNear * inFar / (inFar - inNear);
+ w = 1.0F / w * cotan * inScreenHeight / 2.0F;
+
+ projectedTriangle[i].x *= w;
+ projectedTriangle[i].y *= w;
+ }
+
+ return CalculateProjectedBoxArea2D (projectedTriangle);
+}
+
+//float a = (inFar + inNear) / (inFar - inNear);
+//float b = 2.0F * inNear * inFar / (inFar - inNear);
+//float c = cotan * inScreenHeight / 2.0F;
+
+float CalculateBoxAreaRadialFrustum2 (Vector3f* v, float a, float b, float c)
+{
+ UInt32 i;
+ float w, distance;
+ Vector3f projectedTriangle[8];
+
+ for (i=0;i<8;i++)
+ {
+ projectedTriangle[i] = v[i];
+ distance = Magnitude (projectedTriangle[i]);
+
+ w = a * distance + b;
+ w = 1.0F / w * c;
+
+ projectedTriangle[i].x *= w;
+ projectedTriangle[i].y *= w;
+ }
+
+ return CalculateProjectedBoxArea2D (projectedTriangle);
+
+}
+
+float CalculateTriangleAreaRadialFrustum (
+ Vector3f* v,
+ float inFovy,
+ float inNear,
+ float inFar,
+ float inScreenHeight)
+{
+ UInt32 i;
+ double cotan, w, distance;
+ Vector3f projectedTriangle[3];
+
+ cotan = Deg2Rad (inFovy / 2.0F);
+ cotan = cos (cotan) / sin (cotan);
+
+ for (i=0;i<3;i++)
+ {
+ projectedTriangle[i] = v[i];
+ distance = Magnitude (projectedTriangle[i]);
+
+ w = (inFar + inNear) / (inFar - inNear) * distance
+ + 2.0F * inNear * inFar / (inFar - inNear);
+ w = 1.0F / w;
+
+ projectedTriangle[i].x *= w * cotan * inScreenHeight / 2.0F;
+ projectedTriangle[i].y *= w * cotan * inScreenHeight / 2.0F;
+ }
+
+ return Abs (SignedTriangleArea2D (projectedTriangle));
+}
+//float a = (inFar + inNear) / (inFar - inNear);
+//float b = 2.0F * inNear * inFar / (inFar - inNear);
+//float c = cotan * inScreenHeight / 2.0F;
+
+float CalculateTriangleAreaRadialFrustum2 (Vector3f* v, float a, float b, float c)
+{
+ UInt32 i;
+ float w, distance;
+ Vector3f projectedTriangle[3];
+
+ for (i=0;i<3;i++)
+ {
+ projectedTriangle[i] = v[i];
+ distance = Magnitude (projectedTriangle[i]);
+
+ w = a * distance + b;
+ w = 1.0F / w * c;
+
+ projectedTriangle[i].x *= w;
+ projectedTriangle[i].y *= w;
+ }
+
+ return Abs (SignedTriangleArea2D (projectedTriangle));
+}
+
+float CalculateTriangleAreaRotationless (Vector3f* v, float inFovy, float inScreenWidth, float inScreenHeight, Vector3f& viewPoint)
+{
+ Vector3f normal = Normalize (Cross (v[0] - v[1], v[1] - v[2]));
+ float objectSpaceArea = Magnitude (Cross (v[1] - v[0], v[2] - v[0])) * 0.5F;
+ Vector3f centroid = (v[0] + v[1] + v[2]) / 3.0F;
+ Vector3f difference = viewPoint - centroid;
+ float distance = Magnitude (difference);
+ // We want 1.0 when it faces the tri directly -> 0 degrees
+ // We want 0.0 when the tri is invisible -> 90 degrees
+ // It doesn't matter if the tri faces away from the viewer or not.
+ float angle = Abs (Dot (normal, (difference / distance)));
+
+ float screenSpaceArea =
+ objectSpaceArea
+ * sin (Deg2Rad (inFovy * 0.5F))
+ * inScreenWidth
+ * inScreenHeight
+ * sin (Deg2Rad (inFovy * 0.5F))
+ * angle
+ / distance;
+
+ return screenSpaceArea;
+}
+
+int ClipPolygonAgainstPlane(int vertexCount, const Vector3f *vertex, const Plane& plane, char *location, Vector3f *result)
+{
+ const float kBoundaryEpsilon = 1.0e-3F;
+
+ enum
+ {
+ kPolygonInterior = 1, //## The point lies in the interior of the polygon.
+ kPolygonBoundary = 0, //## The point lies on or very near the boundary of the polygon.
+ kPolygonExterior = -1 //## The point lies outside the polygon.
+ };
+
+ int positive = 0;
+ int negative = 0;
+
+ for (int a = 0; a < vertexCount; a++)
+ {
+ float d = plane.GetDistanceToPoint(vertex[a]);
+ if (d > kBoundaryEpsilon)
+ {
+ location[a] = kPolygonInterior;
+ positive++;
+ }
+ else
+ {
+ if (d < -kBoundaryEpsilon)
+ {
+ location[a] = kPolygonExterior;
+ negative++;
+ }
+ else
+ {
+ location[a] = kPolygonBoundary;
+ }
+ }
+ }
+
+ if (negative == 0)
+ {
+ for (int a = 0; a < vertexCount; a++)
+ result[a] = vertex[a];
+ return vertexCount;
+ }
+ else if (positive == 0)
+ {
+ return 0;
+ }
+
+ int count = 0;
+ int previous = vertexCount - 1;
+ for (int index = 0; index < vertexCount; index++)
+ {
+ int loc = location[index];
+ if (loc == kPolygonExterior)
+ {
+ if (location[previous] == kPolygonInterior)
+ {
+ const Vector3f& v1 = vertex[previous];
+ const Vector3f& v2 = vertex[index];
+ Vector3f dv = v2 - v1;
+
+ float t = plane.GetDistanceToPoint(v2) / plane.GetDistanceToPoint(dv);
+ result[count++] = v2 - dv * t;
+ }
+ }
+ else
+ {
+ const Vector3f& v1 = vertex[index];
+ if ((loc == kPolygonInterior) && (location[previous] == kPolygonExterior))
+ {
+ const Vector3f& v2 = vertex[previous];
+ Vector3f dv = v2 - v1;
+
+ float t = plane.GetDistanceToPoint(v2) / plane.GetDistanceToPoint(dv);
+ result[count++] = v2 - dv * t;
+ }
+
+ result[count++] = v1;
+ }
+
+ previous = index;
+ }
+
+ return count;
+}