コード例 #1
0
//--------------------------------------------------------------------------------------------------
// Compute barycentric coordinates (area coordinates) (u, v, w) for 
// point p with respect to triangle (t0, t1, t2)
// These can be used as weights for interpolating scalar values across the triangle
// Based on section 3.4 in "Real Time collision detection" by Christer Ericson
//--------------------------------------------------------------------------------------------------
cvf::Vec3d GeometryTools::barycentricCoords(const cvf::Vec3d&  t0, const cvf::Vec3d&  t1, const cvf::Vec3d&  t2, const cvf::Vec3d&  p)
{
    // Unnormalized triangle normal
    cvf::Vec3d m = (t1 - t0 ^ t2 - t0);

    // Absolute components for determining projection plane
    int X = 0, Y = 1;
    int Z = findClosestAxis(m);
    switch (Z)
    {
    case 0: X = 1; Y = 2; break; // x is largest, project to the yz plane
    case 1: X = 0; Y = 2; break; // y is largest, project to the xz plane
    case 2: X = 0; Y = 1; break; // z is largest, project to the xy plane
    }

    // Compute areas in plane of largest projection
    // Nominators and one-over-denominator for u and v ratios
    double nu, nv, ood;
    nu = TriArea2D(p[X], p[Y], t1[X], t1[Y], t2[X], t2[Y]); // Area of PBC in yz plane
    nv = TriArea2D(p[X], p[Y], t2[X], t2[Y], t0[X], t0[Y]); // Area of PCA in yz plane
    ood = 1.0f / m[Z];                             // 1/(2*area of ABC in yz plane)

    if (Z == 1) ood = -ood; // For some reason not explained

    // Normalize

    m[0] = nu * ood;
    m[1] = nv * ood;
    m[2] = 1.0f - m[0] - m[1];

    return m;
}
コード例 #2
0
ファイル: Triangle.cpp プロジェクト: d0n3val/Edu-Game-Engine
float3 Triangle::BarycentricUVW(const float3 &point) const
{
	// Implementation from Christer Ericson's Real-Time Collision Detection, pp. 51-52.

	// Unnormalized triangle normal.
	float3 m = Cross(b-a, c-a);

	// Nominators and one-over-denominator for u and v ratios.
	float nu, nv, ood;

	// Absolute components for determining projection plane.
	float x = Abs(m.x);
	float y = Abs(m.y);
	float z = Abs(m.z);

	if (x >= y && x >= z)
	{
		// Project to the yz plane.
		nu = TriArea2D(point.y, point.z, b.y, b.z, c.y, c.z); // Area of PBC in yz-plane.
		nv = TriArea2D(point.y, point.z, c.y, c.z, a.y, a.z); // Area OF PCA in yz-plane.
		ood = 1.f / m.x; // 1 / (2*area of ABC in yz plane)
	}
	else if (y >= z) // Note: The book has a redundant 'if (y >= x)' comparison
	{
		// y is largest, project to the xz-plane.
		nu = TriArea2D(point.x, point.z, b.x, b.z, c.x, c.z);
		nv = TriArea2D(point.x, point.z, c.x, c.z, a.x, a.z);
		ood = 1.f / -m.y;
	}
	else // z is largest, project to the xy-plane.
	{
		nu = TriArea2D(point.x, point.y, b.x, b.y, c.x, c.y);
		nv = TriArea2D(point.x, point.y, c.x, c.y, a.x, a.y);
		ood = 1.f / m.z;
	}
	float u = nu * ood;
	float v = nv * ood;
	float w = 1.f - u - v;
	return float3(u,v,w);
#if 0 // TODO: This version should be more SIMD-friendly, but for some reason, it doesn't return good values for all points inside the triangle.
	float3 v0 = b - a;
	float3 v1 = c - a;
	float3 v2 = point - a;
	float d00 = Dot(v0, v0);
	float d01 = Dot(v0, v1);
	float d02 = Dot(v0, v2);
	float d11 = Dot(v1, v1);
	float d12 = Dot(v1, v2);
	float denom = 1.f / (d00 * d11 - d01 * d01);
	float v = (d11 * d02 - d01 * d12) * denom;
	float w = (d00 * d12 - d01 * d02) * denom;
	float u = 1.0f - v - w;
	return float3(u, v, w);
#endif
}