1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 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 Point& v, const Plane& 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()
{
Point Tmp = mVerts[1];
mVerts[1] = mVerts[2];
mVerts[2] = Tmp;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle area.
* \return the area
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Area() const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle perimeter.
* \return the perimeter
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float Triangle::Perimeter() const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& 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(Point& normal) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
normal = ((p0 - p1)^(p0 - p2)).Normalize();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle denormalized normal.
* \param normal [out] the computed normal
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::DenormalizedNormal(Point& normal) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
normal = ((p0 - p1)^(p0 - p2));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the triangle center.
* \param center [out] the computed center
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::Center(Point& center) const
{
const Point& p0 = mVerts[0];
const Point& p1 = mVerts[1];
const Point& p2 = mVerts[2];
center = (p0 + p1 + p2)*INV3;
}
PartVal Triangle::TestAgainstPlane(const Plane& 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.
Point& p = mVerts[0];
Point& q = mVerts[1];
Point& 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 point on the triangle according to the stabbing information.
* \param u,v [in] point's barycentric coordinates
* \param pt [out] point on triangle
* \param nearvtx [out] index of nearest vertex
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Triangle::ComputePoint(float u, float v, Point& pt, udword* nearvtx) const
{
// Compute point coordinates
pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2];
// Compute nearest vertex if needed
if(nearvtx)
{
// Compute distance vector
Point d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
// Get smallest distance
*nearvtx = d.SmallestAxis();
}
}
void Triangle::Inflate(float fat_coeff, bool constant_border)
{
// Compute triangle center
Point 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++)
{
Point v = mVerts[i] - TriangleCenter;
if(constant_border) v.Normalize();
mVerts[i] += v * fat_coeff;
}
}
|