summaryrefslogtreecommitdiffhomepage
path: root/third-party/Opcode/Ice/IceTriangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third-party/Opcode/Ice/IceTriangle.cpp')
-rw-r--r--third-party/Opcode/Ice/IceTriangle.cpp286
1 files changed, 286 insertions, 0 deletions
diff --git a/third-party/Opcode/Ice/IceTriangle.cpp b/third-party/Opcode/Ice/IceTriangle.cpp
new file mode 100644
index 0000000..e55f73e
--- /dev/null
+++ b/third-party/Opcode/Ice/IceTriangle.cpp
@@ -0,0 +1,286 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Contains a handy triangle class.
+ * \file IceTriangle.cpp
+ * \author Pierre Terdiman
+ * \date January, 17, 2000
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Precompiled Header
+#include "StdAfx.h"
+
+using namespace IceMaths;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Contains a triangle class.
+ *
+ * \class Tri
+ * \author Pierre Terdiman
+ * \version 1.0
+ * \date 08.15.98
+*/
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static sdword VPlaneSideEps(const IcePoint& v, const IcePlane& plane, float epsilon)
+{
+ // Compute distance from current vertex to the plane
+ float Dist = plane.Distance(v);
+ // Compute side:
+ // 1 = the vertex is on the positive side of the plane
+ // -1 = the vertex is on the negative side of the plane
+ // 0 = the vertex is on the plane (within epsilon)
+ return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Flips the winding order.
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::Flip()
+{
+ IcePoint Tmp = mVerts[1];
+ mVerts[1] = mVerts[2];
+ mVerts[2] = Tmp;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle area.
+ * \return the area
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::Area() const
+{
+ const IcePoint& p0 = mVerts[0];
+ const IcePoint& p1 = mVerts[1];
+ const IcePoint& p2 = mVerts[2];
+ return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle perimeter.
+ * \return the perimeter
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::Perimeter() const
+{
+ const IcePoint& p0 = mVerts[0];
+ const IcePoint& p1 = mVerts[1];
+ const IcePoint& p2 = mVerts[2];
+ return p0.Distance(p1)
+ + p0.Distance(p2)
+ + p1.Distance(p2);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle compacity.
+ * \return the compacity
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::Compacity() const
+{
+ float P = Perimeter();
+ if(P==0.0f) return 0.0f;
+ return (4.0f*PI*Area()/(P*P));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle normal.
+ * \param normal [out] the computed normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::Normal(IcePoint& normal) const
+{
+ const IcePoint& p0 = mVerts[0];
+ const IcePoint& p1 = mVerts[1];
+ const IcePoint& p2 = mVerts[2];
+ normal = ((p0 - p1)^(p0 - p2)).Normalize();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle denormalized normal.
+ * \param normal [out] the computed normal
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::DenormalizedNormal(IcePoint& normal) const
+{
+ const IcePoint& p0 = mVerts[0];
+ const IcePoint& p1 = mVerts[1];
+ const IcePoint& p2 = mVerts[2];
+ normal = ((p0 - p1)^(p0 - p2));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle center.
+ * \param center [out] the computed center
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::Center(IcePoint& center) const
+{
+ const IcePoint& p0 = mVerts[0];
+ const IcePoint& p1 = mVerts[1];
+ const IcePoint& p2 = mVerts[2];
+ center = (p0 + p1 + p2)*INV3;
+}
+
+PartVal Triangle::TestAgainstPlane(const IcePlane& plane, float epsilon) const
+{
+ bool Pos = false, Neg = false;
+
+ // Loop through all vertices
+ for(udword i=0;i<3;i++)
+ {
+ // Compute side:
+ sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon);
+
+ if (Side < 0) Neg = true;
+ else if (Side > 0) Pos = true;
+ }
+
+ if (!Pos && !Neg) return TRI_ON_PLANE;
+ else if (Pos && Neg) return TRI_INTERSECT;
+ else if (Pos && !Neg) return TRI_PLUS_SPACE;
+ else if (!Pos && Neg) return TRI_MINUS_SPACE;
+
+ // What?!
+ return TRI_FORCEDWORD;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle moment.
+ * \param m [out] the moment
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+void Triangle::ComputeMoment(Moment& m)
+{
+ // Compute the area of the triangle
+ m.mArea = Area();
+
+ // Compute the centroid
+ Center(m.mCentroid);
+
+ // Second-order components. Handle zero-area faces.
+ IcePoint& p = mVerts[0];
+ IcePoint& q = mVerts[1];
+ IcePoint& r = mVerts[2];
+ if(m.mArea==0.0f)
+ {
+ // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the
+ // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices.
+ m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x);
+ m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y);
+ m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z);
+ m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y);
+ m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z);
+ m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z);
+ m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
+ m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
+ m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
+ }
+ else
+ {
+ const float OneOverTwelve = 1.0f / 12.0f;
+ m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve;
+ m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve;
+ m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve;
+ m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve;
+ m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve;
+ m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve;
+ m.mCovariance.m[2][1] = m.mCovariance.m[1][2];
+ m.mCovariance.m[1][0] = m.mCovariance.m[0][1];
+ m.mCovariance.m[2][0] = m.mCovariance.m[0][2];
+ }
+}
+*/
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle's smallest edge length.
+ * \return the smallest edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::MinEdgeLength() const
+{
+ float Min = MAX_FLOAT;
+ float Length01 = mVerts[0].Distance(mVerts[1]);
+ float Length02 = mVerts[0].Distance(mVerts[2]);
+ float Length12 = mVerts[1].Distance(mVerts[2]);
+ if(Length01 < Min) Min = Length01;
+ if(Length02 < Min) Min = Length02;
+ if(Length12 < Min) Min = Length12;
+ return Min;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the triangle's largest edge length.
+ * \return the largest edge length
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+float Triangle::MaxEdgeLength() const
+{
+ float Max = MIN_FLOAT;
+ float Length01 = mVerts[0].Distance(mVerts[1]);
+ float Length02 = mVerts[0].Distance(mVerts[2]);
+ float Length12 = mVerts[1].Distance(mVerts[2]);
+ if(Length01 > Max) Max = Length01;
+ if(Length02 > Max) Max = Length02;
+ if(Length12 > Max) Max = Length12;
+ return Max;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes a IcePoint on the triangle according to the stabbing information.
+ * \param u,v [in] IcePoint's barycentric coordinates
+ * \param pt [out] IcePoint on triangle
+ * \param nearvtx [out] index of nearest vertex
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void Triangle::ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx) const
+{
+ // Compute IcePoint coordinates
+ pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
+
+ // Compute nearest vertex if needed
+ if(nearvtx)
+ {
+ // Compute distance vector
+ IcePoint d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to IcePoint on the face
+ mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to IcePoint on the face
+ mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to IcePoint on the face
+
+ // Get smallest distance
+ *nearvtx = d.SmallestAxis();
+ }
+}
+
+void Triangle::Inflate(float fat_coeff, bool constant_border)
+{
+ // Compute triangle center
+ IcePoint TriangleCenter;
+ Center(TriangleCenter);
+
+ // Don't normalize?
+ // Normalize => add a constant border, regardless of triangle size
+ // Don't => add more to big triangles
+ for(udword i=0;i<3;i++)
+ {
+ IcePoint v = mVerts[i] - TriangleCenter;
+
+ if(constant_border) v.Normalize();
+
+ mVerts[i] += v * fat_coeff;
+ }
+}